From 39f7eb2985683139c30506839eb7c0894fdaea8f Mon Sep 17 00:00:00 2001 From: Lachlan Date: Wed, 29 Jan 2025 15:41:54 -0800 Subject: [PATCH 01/34] simple tui --- showcase/code-analysis/.gitignore | 11 ++ showcase/code-analysis/README.md | 42 +++++++ showcase/code-analysis/cli/__init__.py | 3 + showcase/code-analysis/cli/__main__.py | 164 +++++++++++++++++++++++++ showcase/code-analysis/knowledge.md | 17 +++ showcase/code-analysis/pyproject.toml | 30 +++++ 6 files changed, 267 insertions(+) create mode 100644 showcase/code-analysis/.gitignore create mode 100644 showcase/code-analysis/README.md create mode 100644 showcase/code-analysis/cli/__init__.py create mode 100644 showcase/code-analysis/cli/__main__.py create mode 100644 showcase/code-analysis/knowledge.md create mode 100644 showcase/code-analysis/pyproject.toml diff --git a/showcase/code-analysis/.gitignore b/showcase/code-analysis/.gitignore new file mode 100644 index 0000000..53aa933 --- /dev/null +++ b/showcase/code-analysis/.gitignore @@ -0,0 +1,11 @@ +__pycache__/ +*.py[cod] +*$py.class +.env +.venv/ +venv/ +.DS_Store +*.log +dist/ +build/ +*.egg-info/ diff --git a/showcase/code-analysis/README.md b/showcase/code-analysis/README.md new file mode 100644 index 0000000..f0398ab --- /dev/null +++ b/showcase/code-analysis/README.md @@ -0,0 +1,42 @@ +# Code Analysis CLI + +A Python CLI application for analyzing GitHub repository complexity. + +## Setup + +```bash +# Create and activate virtual environment +python -m venv .venv +source .venv/bin/activate # On Windows use: .venv\Scripts\activate + +# Install dependencies +pip install -e . + +# Install development dependencies (optional) +pip install -e ".[dev]" +``` + +## Usage + +```bash +# List available commands +python -m cli --help + +# Analyze commit frequency for a repository +python -m cli analyze_commit_frequency /path/to/git/repo +``` + +## Features + +- analyze_commit_frequency: Analyze commit frequency by day +- More features coming soon! + +## Development + +```bash +# Run type checker +mypy cli + +# Format code +black cli +``` diff --git a/showcase/code-analysis/cli/__init__.py b/showcase/code-analysis/cli/__init__.py new file mode 100644 index 0000000..ebf5982 --- /dev/null +++ b/showcase/code-analysis/cli/__init__.py @@ -0,0 +1,3 @@ +"""A Python CLI application.""" + +__version__ = "0.1.0" diff --git a/showcase/code-analysis/cli/__main__.py b/showcase/code-analysis/cli/__main__.py new file mode 100644 index 0000000..4d17537 --- /dev/null +++ b/showcase/code-analysis/cli/__main__.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +from typing import Any, Callable, Dict +import argparse +from git import Repo +from datetime import datetime, timezone +from collections import defaultdict + + +def analyze_commit_frequency(repo_path: str) -> Dict[str, int]: + """Analyze commit frequency by day for a git repository.""" + repo = Repo(repo_path) + frequency: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + date = datetime.fromtimestamp(commit.committed_date, timezone.utc) + day = date.strftime("%Y-%m-%d") + frequency[day] += 1 + + return dict(frequency) + + +def analyze_commit_frequency_by_weekday(repo_path: str) -> Dict[str, int]: + """ + Analyze commit frequency by weekday (e.g., Monday, Tuesday). + """ + repo = Repo(repo_path) + frequency: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + date = datetime.fromtimestamp(commit.committed_date, timezone.utc) + weekday = date.strftime("%A") # e.g., "Monday" + frequency[weekday] += 1 + + return dict(frequency) + + +def analyze_commit_frequency_by_hour(repo_path: str) -> Dict[str, int]: + """ + Analyze commit frequency by hour of day (0-23). + """ + repo = Repo(repo_path) + frequency: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + date = datetime.fromtimestamp(commit.committed_date, timezone.utc) + hour = date.strftime("%H") # e.g., "13" for 1pm + frequency[hour] += 1 + + return dict(frequency) + + +def analyze_average_commit_size(repo_path: str) -> Dict[str, float]: + """ + Compute the average commit size (approximate lines added or removed per commit). + """ + repo = Repo(repo_path) + total_changes = 0 + commit_count = 0 + + for commit in repo.iter_commits(): + # If the commit has no parent (e.g., the initial commit), skip + if not commit.parents: + continue + + # Compare commit to its first parent + diffs = commit.diff(commit.parents[0], create_patch=True) + changes_in_commit = 0 + for diff in diffs: + # diff.diff is a bytes object containing patch data + # A rough approach is to count the number of lines that start with "+" or "-" + # ignoring lines that start with "+++" or "---" in the patch header + patch_lines = diff.diff.decode("utf-8", errors="ignore").split("\n") + for line in patch_lines: + if line.startswith('+') and not line.startswith('+++'): + changes_in_commit += 1 + elif line.startswith('-') and not line.startswith('---'): + changes_in_commit += 1 + + total_changes += changes_in_commit + commit_count += 1 + + average_changes = total_changes / commit_count if commit_count else 0 + return {"average_commit_size": average_changes} + + +def analyze_file_change_frequency(repo_path: str) -> Dict[str, int]: + """ + Analyze how often each file is changed in the repository. + """ + repo = Repo(repo_path) + file_frequency: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + # Skip the initial commit (no parent to compare against) + if not commit.parents: + continue + + parent = commit.parents[0] + # diff() returns a list of diff objects representing file changes + diffs = commit.diff(parent) + + for diff in diffs: + # a_path and b_path might be different if the file was renamed + file_path = diff.a_path or diff.b_path + file_frequency[file_path] += 1 + + return dict(file_frequency) + + +def analyze_contributor_activity(repo_path: str) -> Dict[str, int]: + """Analyze commit count per contributor in a git repository.""" + repo = Repo(repo_path) + activity: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + author = f"{commit.author.name} <{commit.author.email}>" + activity[author] += 1 + + return dict(activity) + + +# Dictionary mapping command names to their corresponding functions +COMMANDS: Dict[str, Callable[..., Dict[str, Any]]] = { + "analyze_commit_frequency": analyze_commit_frequency, + "analyze_contributor_activity": analyze_contributor_activity, + "analyze_commit_frequency_by_weekday": analyze_commit_frequency_by_weekday, + "analyze_commit_frequency_by_hour": analyze_commit_frequency_by_hour, + "analyze_average_commit_size": analyze_average_commit_size, + "analyze_file_change_frequency": analyze_file_change_frequency, +} + + +def main() -> None: + parser = argparse.ArgumentParser(description="Analyze GitHub repository complexity") + parser.add_argument( + "command", + choices=list(COMMANDS.keys()), + help="The analysis command to run", + ) + parser.add_argument( + "repo_path", + help="Path to the git repository to analyze", + ) + + args = parser.parse_args() + + try: + # Get the function corresponding to the command + command_func = COMMANDS[args.command] + + # Execute the command and get the results + results = command_func(args.repo_path) + + # Print results + print(f"\n{args.command} results:") + for key, value in sorted(results.items()): + print(f"{key}: {value}") + + except Exception as e: + print(f"Error analyzing repository: {e}") + + +if __name__ == "__main__": + main() diff --git a/showcase/code-analysis/knowledge.md b/showcase/code-analysis/knowledge.md new file mode 100644 index 0000000..be474f6 --- /dev/null +++ b/showcase/code-analysis/knowledge.md @@ -0,0 +1,17 @@ +# Python CLI Template Knowledge + +## Project Overview +A minimal Python CLI application template with modern Python features and type hints. + +## Key Features +- Uses virtual environments for isolation +- Type hints and mypy for static type checking +- Modern Python packaging with pyproject.toml +- Black for code formatting + +## Verifying changes +After every change, run: +```bash +mypy cli && black --check cli +``` +This will check for type errors and formatting issues. diff --git a/showcase/code-analysis/pyproject.toml b/showcase/code-analysis/pyproject.toml new file mode 100644 index 0000000..59d4118 --- /dev/null +++ b/showcase/code-analysis/pyproject.toml @@ -0,0 +1,30 @@ +[project] +name = "cli" +version = "0.1.0" +description = "A Python CLI application for analyzing GitHub repository complexity" +requires-python = ">=3.8" +dependencies = [ + "gitpython>=3.1.42", +] + +[project.optional-dependencies] +dev = [ + "mypy>=1.8.0", + "black>=24.1.1", + "pytest>=8.0.0", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.mypy] +python_version = "3.8" +strict = true +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = true + +[tool.black] +line-length = 88 +target-version = ['py38'] From 0874cc95e40c24ebd24fea4e7222b34909b6b4bd Mon Sep 17 00:00:00 2001 From: Lachlan Date: Wed, 29 Jan 2025 15:48:15 -0800 Subject: [PATCH 02/34] json output --- showcase/code-analysis/cli/__main__.py | 50 +++++++++++++++++++------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/showcase/code-analysis/cli/__main__.py b/showcase/code-analysis/cli/__main__.py index 4d17537..7cd3c7c 100644 --- a/showcase/code-analysis/cli/__main__.py +++ b/showcase/code-analysis/cli/__main__.py @@ -24,14 +24,23 @@ def analyze_commit_frequency_by_weekday(repo_path: str) -> Dict[str, int]: Analyze commit frequency by weekday (e.g., Monday, Tuesday). """ repo = Repo(repo_path) - frequency: Dict[str, int] = defaultdict(int) + # Initialize all weekdays with zero count + frequency = { + "Monday": 0, + "Tuesday": 0, + "Wednesday": 0, + "Thursday": 0, + "Friday": 0, + "Saturday": 0, + "Sunday": 0, + } for commit in repo.iter_commits(): date = datetime.fromtimestamp(commit.committed_date, timezone.utc) weekday = date.strftime("%A") # e.g., "Monday" frequency[weekday] += 1 - return dict(frequency) + return frequency def analyze_commit_frequency_by_hour(repo_path: str) -> Dict[str, int]: @@ -39,14 +48,15 @@ def analyze_commit_frequency_by_hour(repo_path: str) -> Dict[str, int]: Analyze commit frequency by hour of day (0-23). """ repo = Repo(repo_path) - frequency: Dict[str, int] = defaultdict(int) + # Initialize all hours with zero count + frequency = {f"{hour:02d}": 0 for hour in range(24)} for commit in repo.iter_commits(): date = datetime.fromtimestamp(commit.committed_date, timezone.utc) hour = date.strftime("%H") # e.g., "13" for 1pm frequency[hour] += 1 - return dict(frequency) + return frequency def analyze_average_commit_size(repo_path: str) -> Dict[str, float]: @@ -66,14 +76,19 @@ def analyze_average_commit_size(repo_path: str) -> Dict[str, float]: diffs = commit.diff(commit.parents[0], create_patch=True) changes_in_commit = 0 for diff in diffs: - # diff.diff is a bytes object containing patch data + if not diff.diff: + continue + # diff.diff can be either string or bytes # A rough approach is to count the number of lines that start with "+" or "-" # ignoring lines that start with "+++" or "---" in the patch header - patch_lines = diff.diff.decode("utf-8", errors="ignore").split("\n") + if isinstance(diff.diff, bytes): + patch_lines = diff.diff.decode("utf-8", errors="ignore").split("\n") + else: + patch_lines = diff.diff.split("\n") for line in patch_lines: - if line.startswith('+') and not line.startswith('+++'): + if line.startswith("+") and not line.startswith("+++"): changes_in_commit += 1 - elif line.startswith('-') and not line.startswith('---'): + elif line.startswith("-") and not line.startswith("---"): changes_in_commit += 1 total_changes += changes_in_commit @@ -102,7 +117,8 @@ def analyze_file_change_frequency(repo_path: str) -> Dict[str, int]: for diff in diffs: # a_path and b_path might be different if the file was renamed file_path = diff.a_path or diff.b_path - file_frequency[file_path] += 1 + if file_path: # Only count if we have a valid path + file_frequency[file_path] += 1 return dict(file_frequency) @@ -141,6 +157,11 @@ def main() -> None: "repo_path", help="Path to the git repository to analyze", ) + parser.add_argument( + "--json", + action="store_true", + help="Output results in JSON format", + ) args = parser.parse_args() @@ -152,9 +173,14 @@ def main() -> None: results = command_func(args.repo_path) # Print results - print(f"\n{args.command} results:") - for key, value in sorted(results.items()): - print(f"{key}: {value}") + if args.json: + import json + + print(json.dumps(results, indent=2)) + else: + print(f"\n{args.command} results:") + for key, value in sorted(results.items()): + print(f"{key}: {value}") except Exception as e: print(f"Error analyzing repository: {e}") From 2d6f2e481b9713d42a431ddab2bdf76cc160cf54 Mon Sep 17 00:00:00 2001 From: Lachlan Date: Wed, 29 Jan 2025 16:15:35 -0800 Subject: [PATCH 03/34] web app --- showcase/code-analysis/README.md | 12 ++- showcase/code-analysis/cli/__main__.py | 141 ++----------------------- showcase/code-analysis/pyproject.toml | 2 + 3 files changed, 20 insertions(+), 135 deletions(-) diff --git a/showcase/code-analysis/README.md b/showcase/code-analysis/README.md index f0398ab..e217cac 100644 --- a/showcase/code-analysis/README.md +++ b/showcase/code-analysis/README.md @@ -24,6 +24,9 @@ python -m cli --help # Analyze commit frequency for a repository python -m cli analyze_commit_frequency /path/to/git/repo + +# Output results in JSON format +python -m cli analyze_commit_frequency /path/to/git/repo --json ``` ## Features @@ -35,8 +38,13 @@ python -m cli analyze_commit_frequency /path/to/git/repo ```bash # Run type checker -mypy cli +mypy cli app # Format code -black cli +black cli app + +# Run FastAPI server +uvicorn app.main:app --reload ``` + +The FastAPI app will be available at http://localhost:8000 with automatic API documentation at http://localhost:8000/docs. diff --git a/showcase/code-analysis/cli/__main__.py b/showcase/code-analysis/cli/__main__.py index 7cd3c7c..3f21977 100644 --- a/showcase/code-analysis/cli/__main__.py +++ b/showcase/code-analysis/cli/__main__.py @@ -1,139 +1,14 @@ #!/usr/bin/env python3 from typing import Any, Callable, Dict import argparse -from git import Repo -from datetime import datetime, timezone -from collections import defaultdict - - -def analyze_commit_frequency(repo_path: str) -> Dict[str, int]: - """Analyze commit frequency by day for a git repository.""" - repo = Repo(repo_path) - frequency: Dict[str, int] = defaultdict(int) - - for commit in repo.iter_commits(): - date = datetime.fromtimestamp(commit.committed_date, timezone.utc) - day = date.strftime("%Y-%m-%d") - frequency[day] += 1 - - return dict(frequency) - - -def analyze_commit_frequency_by_weekday(repo_path: str) -> Dict[str, int]: - """ - Analyze commit frequency by weekday (e.g., Monday, Tuesday). - """ - repo = Repo(repo_path) - # Initialize all weekdays with zero count - frequency = { - "Monday": 0, - "Tuesday": 0, - "Wednesday": 0, - "Thursday": 0, - "Friday": 0, - "Saturday": 0, - "Sunday": 0, - } - - for commit in repo.iter_commits(): - date = datetime.fromtimestamp(commit.committed_date, timezone.utc) - weekday = date.strftime("%A") # e.g., "Monday" - frequency[weekday] += 1 - - return frequency - - -def analyze_commit_frequency_by_hour(repo_path: str) -> Dict[str, int]: - """ - Analyze commit frequency by hour of day (0-23). - """ - repo = Repo(repo_path) - # Initialize all hours with zero count - frequency = {f"{hour:02d}": 0 for hour in range(24)} - - for commit in repo.iter_commits(): - date = datetime.fromtimestamp(commit.committed_date, timezone.utc) - hour = date.strftime("%H") # e.g., "13" for 1pm - frequency[hour] += 1 - - return frequency - - -def analyze_average_commit_size(repo_path: str) -> Dict[str, float]: - """ - Compute the average commit size (approximate lines added or removed per commit). - """ - repo = Repo(repo_path) - total_changes = 0 - commit_count = 0 - - for commit in repo.iter_commits(): - # If the commit has no parent (e.g., the initial commit), skip - if not commit.parents: - continue - - # Compare commit to its first parent - diffs = commit.diff(commit.parents[0], create_patch=True) - changes_in_commit = 0 - for diff in diffs: - if not diff.diff: - continue - # diff.diff can be either string or bytes - # A rough approach is to count the number of lines that start with "+" or "-" - # ignoring lines that start with "+++" or "---" in the patch header - if isinstance(diff.diff, bytes): - patch_lines = diff.diff.decode("utf-8", errors="ignore").split("\n") - else: - patch_lines = diff.diff.split("\n") - for line in patch_lines: - if line.startswith("+") and not line.startswith("+++"): - changes_in_commit += 1 - elif line.startswith("-") and not line.startswith("---"): - changes_in_commit += 1 - - total_changes += changes_in_commit - commit_count += 1 - - average_changes = total_changes / commit_count if commit_count else 0 - return {"average_commit_size": average_changes} - - -def analyze_file_change_frequency(repo_path: str) -> Dict[str, int]: - """ - Analyze how often each file is changed in the repository. - """ - repo = Repo(repo_path) - file_frequency: Dict[str, int] = defaultdict(int) - - for commit in repo.iter_commits(): - # Skip the initial commit (no parent to compare against) - if not commit.parents: - continue - - parent = commit.parents[0] - # diff() returns a list of diff objects representing file changes - diffs = commit.diff(parent) - - for diff in diffs: - # a_path and b_path might be different if the file was renamed - file_path = diff.a_path or diff.b_path - if file_path: # Only count if we have a valid path - file_frequency[file_path] += 1 - - return dict(file_frequency) - - -def analyze_contributor_activity(repo_path: str) -> Dict[str, int]: - """Analyze commit count per contributor in a git repository.""" - repo = Repo(repo_path) - activity: Dict[str, int] = defaultdict(int) - - for commit in repo.iter_commits(): - author = f"{commit.author.name} <{commit.author.email}>" - activity[author] += 1 - - return dict(activity) - +from cli.git_analysis import ( + analyze_commit_frequency, + analyze_contributor_activity, + analyze_commit_frequency_by_weekday, + analyze_commit_frequency_by_hour, + analyze_average_commit_size, + analyze_file_change_frequency, +) # Dictionary mapping command names to their corresponding functions COMMANDS: Dict[str, Callable[..., Dict[str, Any]]] = { diff --git a/showcase/code-analysis/pyproject.toml b/showcase/code-analysis/pyproject.toml index 59d4118..c69d8cf 100644 --- a/showcase/code-analysis/pyproject.toml +++ b/showcase/code-analysis/pyproject.toml @@ -5,6 +5,8 @@ description = "A Python CLI application for analyzing GitHub repository complexi requires-python = ">=3.8" dependencies = [ "gitpython>=3.1.42", + "fastapi>=0.109.2", + "uvicorn>=0.27.1", ] [project.optional-dependencies] From e75bd70473395d6bc30ae2edce247334e8935b3c Mon Sep 17 00:00:00 2001 From: Lachlan Date: Wed, 29 Jan 2025 16:41:01 -0800 Subject: [PATCH 04/34] chrome extension... --- showcase/code-analysis/knowledge.md | 54 ++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/showcase/code-analysis/knowledge.md b/showcase/code-analysis/knowledge.md index be474f6..1746ed8 100644 --- a/showcase/code-analysis/knowledge.md +++ b/showcase/code-analysis/knowledge.md @@ -12,6 +12,58 @@ A minimal Python CLI application template with modern Python features and type h ## Verifying changes After every change, run: ```bash -mypy cli && black --check cli +mypy cli app && black --check cli app ``` This will check for type errors and formatting issues. + +## Project Structure +- `cli/`: Command-line interface for git analysis +- `app/`: FastAPI web service for git analysis +- `extension/`: Chrome extension for GitHub integration + +## Chrome Extension +The extension activates on GitHub repository pages and provides: +- Analysis popup accessible via toolbar icon +- Direct integration with local FastAPI server +- JSON visualization of repository metrics + +### Architecture Constraints +Git analysis requires a backend service because: +- GitPython needs filesystem access +- Git operations require system-level access +- Cannot run Python directly in extension + +### Alternative Approaches Investigated +Client-side options have limitations: +- Pyodide (WASM Python): No filesystem/git access +- WebContainer API: Limited browser support, sandboxed + - Requires 'wasm-unsafe-eval' in CSP + - Must load from CDN or package + - Resets on popup close +- isomorphic-git: Requires fetching full repo data first + +## Project Structure +- `cli/`: Command-line interface for git analysis +- `app/`: FastAPI web service for git analysis +- `extension/`: Chrome extension for GitHub integration + +## Chrome Extension +The extension activates on GitHub repository pages and provides: +- Analysis popup accessible via toolbar icon +- Direct integration with local FastAPI server +- JSON visualization of repository metrics + +### Architecture Constraints +Git analysis requires a backend service because: +- GitPython needs filesystem access +- Git operations require system-level access +- Cannot run Python directly in extension + +### Alternative Approaches Investigated +Client-side options have limitations: +- Pyodide (WASM Python): No filesystem/git access +- WebContainer API: Limited browser support, sandboxed + - Requires 'wasm-unsafe-eval' in CSP + - Must load from CDN or package + - Resets on popup close +- isomorphic-git: Requires fetching full repo data first From de4022a7057e18c82434a2334775a696de78cda4 Mon Sep 17 00:00:00 2001 From: Lachlan Date: Wed, 29 Jan 2025 17:07:57 -0800 Subject: [PATCH 05/34] chrome extension --- showcase/code-analysis/README.md | 87 +++++++++--- showcase/code-analysis/app/__init__.py | 1 + showcase/code-analysis/app/main.py | 109 ++++++++++++++ showcase/code-analysis/cli/git_analysis.py | 133 ++++++++++++++++++ .../code-analysis/extension/background.js | 17 +++ showcase/code-analysis/extension/content.js | 57 ++++++++ .../code-analysis/extension/manifest.json | 28 ++++ showcase/code-analysis/extension/popup.html | 56 ++++++++ showcase/code-analysis/extension/popup.js | 130 +++++++++++++++++ showcase/code-analysis/knowledge.md | 6 + showcase/code-analysis/start_server.sh | 2 + 11 files changed, 604 insertions(+), 22 deletions(-) create mode 100644 showcase/code-analysis/app/__init__.py create mode 100644 showcase/code-analysis/app/main.py create mode 100644 showcase/code-analysis/cli/git_analysis.py create mode 100644 showcase/code-analysis/extension/background.js create mode 100644 showcase/code-analysis/extension/content.js create mode 100644 showcase/code-analysis/extension/manifest.json create mode 100644 showcase/code-analysis/extension/popup.html create mode 100644 showcase/code-analysis/extension/popup.js create mode 100755 showcase/code-analysis/start_server.sh diff --git a/showcase/code-analysis/README.md b/showcase/code-analysis/README.md index e217cac..f00ada9 100644 --- a/showcase/code-analysis/README.md +++ b/showcase/code-analysis/README.md @@ -1,9 +1,27 @@ -# Code Analysis CLI +# GitHub Repository Analyzer -A Python CLI application for analyzing GitHub repository complexity. +A Chrome extension that analyzes GitHub repositories for development patterns and metrics. -## Setup +## Features +- Commit frequency analysis +- Contributor activity tracking +- Commit patterns by weekday +- Average commit size metrics + +## Prerequisites +- Python 3.8 or higher +- Google Chrome browser +- Git + +## Setup Instructions + +### 1. Clone the Repository +```bash +git clone +cd code-analysis +``` +### 2. Set Up Python Environment ```bash # Create and activate virtual environment python -m venv .venv @@ -16,35 +34,60 @@ pip install -e . pip install -e ".[dev]" ``` -## Usage - +### 3. Start the Backend Server ```bash -# List available commands -python -m cli --help - -# Analyze commit frequency for a repository -python -m cli analyze_commit_frequency /path/to/git/repo - -# Output results in JSON format -python -m cli analyze_commit_frequency /path/to/git/repo --json +# Start the FastAPI server +./start_server.sh ``` +The server will run at http://localhost:8000 -## Features +### 4. Install Chrome Extension +1. Open Chrome and navigate to `chrome://extensions/` +2. Enable "Developer mode" in the top right +3. Click "Load unpacked" +4. Select the `extension` directory from this project -- analyze_commit_frequency: Analyze commit frequency by day -- More features coming soon! +### 5. Using the Extension +1. Navigate to any GitHub repository +2. Click the extension icon in Chrome's toolbar +3. Click "Analyze Repository" to see metrics ## Development +### Running Type Checks ```bash -# Run type checker mypy cli app +``` -# Format code +### Format Code +```bash black cli app - -# Run FastAPI server -uvicorn app.main:app --reload ``` -The FastAPI app will be available at http://localhost:8000 with automatic API documentation at http://localhost:8000/docs. +### API Documentation +When the server is running, visit: +- http://localhost:8000/docs for interactive API documentation +- http://localhost:8000/redoc for alternative documentation view + +## Troubleshooting + +### Common Issues +1. If the extension shows "No repository detected": + - Refresh the GitHub page + - Make sure you're on a repository page + +2. If analysis fails: + - Check that the backend server is running + - Look for errors in the server logs + +3. If the extension doesn't load: + - Check Chrome's extension page for errors + - Try reloading the extension + +### Server Logs +The FastAPI server logs all operations. Check the terminal where you ran `start_server.sh` for detailed error messages. + +## Architecture +- `cli/`: Command-line interface for git analysis +- `app/`: FastAPI web service +- `extension/`: Chrome extension files diff --git a/showcase/code-analysis/app/__init__.py b/showcase/code-analysis/app/__init__.py new file mode 100644 index 0000000..6b197eb --- /dev/null +++ b/showcase/code-analysis/app/__init__.py @@ -0,0 +1 @@ +"""FastAPI application for git repository analysis.""" diff --git a/showcase/code-analysis/app/main.py b/showcase/code-analysis/app/main.py new file mode 100644 index 0000000..04679d3 --- /dev/null +++ b/showcase/code-analysis/app/main.py @@ -0,0 +1,109 @@ +import os +import tempfile +import logging +from git import Repo +from fastapi import FastAPI, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from typing import Dict, Union +from pydantic import BaseModel +from cli.git_analysis import ( + analyze_commit_frequency, + analyze_contributor_activity, + analyze_commit_frequency_by_weekday, + analyze_commit_frequency_by_hour, + analyze_average_commit_size, + analyze_file_change_frequency, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +app = FastAPI(title="Git Analysis API") + +# Enable CORS +app.add_middleware( + CORSMiddleware, + allow_origins=["chrome-extension://*"], # Allow requests from any Chrome extension + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# Store repo paths temporarily +repo_cache: Dict[str, str] = {} + + +class CloneRequest(BaseModel): + url: str + + +@app.post("/clone") +async def clone_repository(request: CloneRequest) -> Dict[str, str]: + """Clone a git repository and return a temporary ID to reference it.""" + try: + # Create a temporary directory + temp_dir = tempfile.mkdtemp() + logger.info(f"Created temp directory: {temp_dir}") + + # Clone the repository + logger.info(f"Cloning repository from {request.url}") + repo = Repo.clone_from(request.url, temp_dir) + + # Generate a simple ID (you might want to use UUID in production) + repo_id = str(hash(request.url)) + + # Store the mapping + repo_cache[repo_id] = temp_dir + logger.info(f"Successfully cloned repository. ID: {repo_id}") + + return {"repo_id": repo_id} + except Exception as e: + logger.error(f"Error cloning repository: {str(e)}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + + +@app.get("/analyze/{analysis_type}") +async def analyze_repo( + analysis_type: str, repo_id: str +) -> Dict[str, Union[int, float]]: + """Analyze a git repository using the specified analysis type.""" + try: + # Get repo path from cache + repo_path = repo_cache.get(repo_id) + if not repo_path: + logger.error(f"Repository not found for ID: {repo_id}") + raise HTTPException( + status_code=404, detail="Repository not found. Please clone it first." + ) + + logger.info(f"Analyzing repository at {repo_path}") + + analysis_functions = { + "commit-frequency": analyze_commit_frequency, + "contributor-activity": analyze_contributor_activity, + "commit-frequency-by-weekday": analyze_commit_frequency_by_weekday, + "commit-frequency-by-hour": analyze_commit_frequency_by_hour, + "average-commit-size": analyze_average_commit_size, + "file-change-frequency": analyze_file_change_frequency, + } + + if analysis_type not in analysis_functions: + logger.error(f"Invalid analysis type: {analysis_type}") + raise HTTPException( + status_code=400, + detail=f"Invalid analysis type. Must be one of: {', '.join(analysis_functions.keys())}", + ) # Execute analysis + logger.info(f"Running {analysis_type} analysis") + results = analysis_functions[analysis_type](repo_path) + logger.info(f"Analysis complete: {results}") + + # Cast the dictionary to the expected type + if not isinstance(results, dict): + raise HTTPException( + status_code=500, detail="Analysis returned invalid type" + ) + return results + except Exception as e: + logger.error(f"Error during analysis: {str(e)}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) diff --git a/showcase/code-analysis/cli/git_analysis.py b/showcase/code-analysis/cli/git_analysis.py new file mode 100644 index 0000000..7ddf9d9 --- /dev/null +++ b/showcase/code-analysis/cli/git_analysis.py @@ -0,0 +1,133 @@ +from typing import Dict +from git import Repo +from datetime import datetime, timezone +from collections import defaultdict + + +def analyze_commit_frequency(repo_path: str) -> Dict[str, int]: + """Analyze commit frequency by day for a git repository.""" + repo = Repo(repo_path) + frequency: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + date = datetime.fromtimestamp(commit.committed_date, timezone.utc) + day = date.strftime("%Y-%m-%d") + frequency[day] += 1 + + return dict(frequency) + + +def analyze_commit_frequency_by_weekday(repo_path: str) -> Dict[str, int]: + """ + Analyze commit frequency by weekday (e.g., Monday, Tuesday). + """ + repo = Repo(repo_path) + # Initialize all weekdays with zero count + frequency = { + "Monday": 0, + "Tuesday": 0, + "Wednesday": 0, + "Thursday": 0, + "Friday": 0, + "Saturday": 0, + "Sunday": 0, + } + + for commit in repo.iter_commits(): + date = datetime.fromtimestamp(commit.committed_date, timezone.utc) + weekday = date.strftime("%A") # e.g., "Monday" + frequency[weekday] += 1 + + return frequency + + +def analyze_commit_frequency_by_hour(repo_path: str) -> Dict[str, int]: + """ + Analyze commit frequency by hour of day (0-23). + """ + repo = Repo(repo_path) + # Initialize all hours with zero count + frequency = {f"{hour:02d}": 0 for hour in range(24)} + + for commit in repo.iter_commits(): + date = datetime.fromtimestamp(commit.committed_date, timezone.utc) + hour = date.strftime("%H") # e.g., "13" for 1pm + frequency[hour] += 1 + + return frequency + + +def analyze_average_commit_size(repo_path: str) -> Dict[str, float]: + """ + Compute the average commit size (approximate lines added or removed per commit). + """ + repo = Repo(repo_path) + total_changes = 0 + commit_count = 0 + + for commit in repo.iter_commits(): + # If the commit has no parent (e.g., the initial commit), skip + if not commit.parents: + continue + + # Compare commit to its first parent + diffs = commit.diff(commit.parents[0], create_patch=True) + changes_in_commit = 0 + for diff in diffs: + if not diff.diff: + continue + # diff.diff can be either string or bytes + # A rough approach is to count the number of lines that start with "+" or "-" + # ignoring lines that start with "+++" or "---" in the patch header + if isinstance(diff.diff, bytes): + patch_lines = diff.diff.decode("utf-8", errors="ignore").split("\n") + else: + patch_lines = diff.diff.split("\n") + for line in patch_lines: + if line.startswith("+") and not line.startswith("+++"): + changes_in_commit += 1 + elif line.startswith("-") and not line.startswith("---"): + changes_in_commit += 1 + + total_changes += changes_in_commit + commit_count += 1 + + average_changes = total_changes / commit_count if commit_count else 0 + return {"average_commit_size": average_changes} + + +def analyze_file_change_frequency(repo_path: str) -> Dict[str, int]: + """ + Analyze how often each file is changed in the repository. + """ + repo = Repo(repo_path) + file_frequency: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + # Skip the initial commit (no parent to compare against) + if not commit.parents: + continue + + parent = commit.parents[0] + # diff() returns a list of diff objects representing file changes + diffs = commit.diff(parent) + + for diff in diffs: + # a_path and b_path might be different if the file was renamed + file_path = diff.a_path or diff.b_path + if file_path: # Only count if we have a valid path + file_frequency[file_path] += 1 + + return dict(file_frequency) + + +def analyze_contributor_activity(repo_path: str) -> Dict[str, int]: + """Analyze commit count per contributor in a git repository.""" + repo = Repo(repo_path) + activity: Dict[str, int] = defaultdict(int) + + for commit in repo.iter_commits(): + author = f"{commit.author.name} <{commit.author.email}>" + activity[author] += 1 + + return dict(activity) diff --git a/showcase/code-analysis/extension/background.js b/showcase/code-analysis/extension/background.js new file mode 100644 index 0000000..06360db --- /dev/null +++ b/showcase/code-analysis/extension/background.js @@ -0,0 +1,17 @@ +// Store repository info from content scripts +let currentRepoInfo = null; + +// Listen for messages from content script +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'REPO_DETECTED') { + currentRepoInfo = message.data; + } +}); + +// Listen for messages from popup +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'GET_REPO_INFO') { + sendResponse({ data: currentRepoInfo }); + } + return true; // Keep channel open for async response +}); diff --git a/showcase/code-analysis/extension/content.js b/showcase/code-analysis/extension/content.js new file mode 100644 index 0000000..6a39db4 --- /dev/null +++ b/showcase/code-analysis/extension/content.js @@ -0,0 +1,57 @@ +// Check if we're on a repository page +function isRepositoryPage() { + // GitHub repository URLs follow the pattern: github.com/owner/repo + const path = window.location.pathname; + const pathParts = path.split('/').filter(Boolean); + return pathParts.length >= 2; +} + +// Extract repository information +function getRepositoryInfo() { + if (!isRepositoryPage()) return null; + + const [owner, repo] = window.location.pathname + .split('/') + .filter(Boolean) + .slice(0, 2); + + return { + owner, + repo, + url: window.location.href + }; +} + +// Initialize when the page loads +function init() { + const repoInfo = getRepositoryInfo(); + if (repoInfo) { + console.log('GitHub Repository Analyzer activated:', repoInfo); + // Send repository information to the extension + chrome.runtime.sendMessage({ + type: 'REPO_DETECTED', + data: repoInfo + }); + } +} + +// Run initialization +init(); + +// Listen for navigation changes (for single page app navigation) +let lastPath = window.location.pathname; +new MutationObserver(() => { + const currentPath = window.location.pathname; + if (currentPath !== lastPath) { + lastPath = currentPath; + init(); + } +}).observe(document.body, { childList: true, subtree: true }); + +// Listen for messages from the popup +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'GET_REPO_INFO') { + sendResponse({ data: getRepositoryInfo() }); + } + return true; // Required to use sendResponse asynchronously +}); diff --git a/showcase/code-analysis/extension/manifest.json b/showcase/code-analysis/extension/manifest.json new file mode 100644 index 0000000..a8c1bff --- /dev/null +++ b/showcase/code-analysis/extension/manifest.json @@ -0,0 +1,28 @@ +{ + "manifest_version": 3, + "name": "GitHub Repository Analyzer", + "version": "1.0", + "description": "Analyzes GitHub repositories for complexity and development patterns", + "permissions": [ + "activeTab" + ], + "host_permissions": [ + "https://github.com/*", + "http://localhost:8000/*" + ], + "action": { + "default_popup": "popup.html" + }, + "background": { + "service_worker": "background.js" + }, + "content_scripts": [ + { + "matches": ["https://github.com/*"], + "js": ["content.js"] + } + ], + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'" + } +} diff --git a/showcase/code-analysis/extension/popup.html b/showcase/code-analysis/extension/popup.html new file mode 100644 index 0000000..38728e1 --- /dev/null +++ b/showcase/code-analysis/extension/popup.html @@ -0,0 +1,56 @@ + + + + GitHub Repository Analyzer + + + +
+

GitHub Repository Analyzer

+
+

Navigate to a GitHub repository to analyze it.

+
+ +
+ + + diff --git a/showcase/code-analysis/extension/popup.js b/showcase/code-analysis/extension/popup.js new file mode 100644 index 0000000..fa64a03 --- /dev/null +++ b/showcase/code-analysis/extension/popup.js @@ -0,0 +1,130 @@ +const API_URL = 'http://localhost:8000'; + +// Helper to format JSON for display +function formatJSON(obj) { + return JSON.stringify(obj, null, 2); +} + +// Clone repository and get repo ID +async function cloneRepository(repoUrl) { + try { + const response = await fetch(`${API_URL}/clone`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ url: repoUrl }), + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.error('Error cloning repository:', error); + throw error; + } +} + +// Fetch analysis results from the API +async function fetchAnalysis(analysisType, repoId) { + try { + const response = await fetch( + `${API_URL}/analyze/${analysisType}?repo_id=${encodeURIComponent(repoId)}` + ); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.error('Error fetching analysis:', error); + return { error: error.message }; + } +} + +// Display analysis results in the popup +function displayResults(results, analysisType) { + const resultsDiv = document.getElementById('analysis-results'); + const section = document.createElement('div'); + section.className = 'analysis-type'; + section.innerHTML = ` +

${analysisType}

+
${formatJSON(results)}
+ `; + resultsDiv.appendChild(section); +} + +// Initialize popup +document.addEventListener('DOMContentLoaded', () => { + // Query for active tab + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + const tab = tabs[0]; + if (!tab.url?.includes('github.com')) { + document.getElementById('repo-info').innerHTML = ` +

Please navigate to a GitHub repository to analyze it.

+ `; + return; + } + + // Get repository info from background script + chrome.runtime.sendMessage({ type: 'GET_REPO_INFO' }, (response) => { + const repoInfo = document.getElementById('repo-info'); + const analysisControls = document.getElementById('analysis-controls'); + + if (response?.data) { + const { owner, repo } = response.data; + const repoUrl = `https://github.com/${owner}/${repo}.git`; + + repoInfo.innerHTML = ` +

Owner: ${owner}

+

Repository: ${repo}

+ `; + + // Show analysis controls + analysisControls.style.display = 'block'; + + // Setup analyze button + const analyzeBtn = document.getElementById('analyze-btn'); + analyzeBtn.addEventListener('click', async () => { + try { + analyzeBtn.disabled = true; + analyzeBtn.textContent = 'Cloning...'; + + // First clone the repository + const { repo_id } = await cloneRepository(repoUrl); + + analyzeBtn.textContent = 'Analyzing...'; + + // Clear previous results + document.getElementById('analysis-results').innerHTML = ''; + + // Fetch each type of analysis + const analysisTypes = [ + 'commit-frequency', + 'contributor-activity', + 'commit-frequency-by-weekday', + 'average-commit-size' + ]; + + for (const type of analysisTypes) { + const results = await fetchAnalysis(type, repo_id); + displayResults(results, type); + } + } catch (error) { + document.getElementById('analysis-results').innerHTML = ` +
+ Error: ${error.message} +
+ `; + } finally { + analyzeBtn.disabled = false; + analyzeBtn.textContent = 'Analyze Repository'; + } + }); + } else { + repoInfo.innerHTML = ` +

No repository detected. Please refresh the page if you're on a GitHub repository.

+ `; + } + }); + }); +}); diff --git a/showcase/code-analysis/knowledge.md b/showcase/code-analysis/knowledge.md index 1746ed8..152a2a9 100644 --- a/showcase/code-analysis/knowledge.md +++ b/showcase/code-analysis/knowledge.md @@ -33,6 +33,12 @@ Git analysis requires a backend service because: - Git operations require system-level access - Cannot run Python directly in extension +### Chrome Extension Architecture +- Use background script for persistent state between content script and popup +- Content script injects into GitHub pages to extract repo info +- Popup must handle case where content script isn't ready +- Always use DOMContentLoaded in popup script + ### Alternative Approaches Investigated Client-side options have limitations: - Pyodide (WASM Python): No filesystem/git access diff --git a/showcase/code-analysis/start_server.sh b/showcase/code-analysis/start_server.sh new file mode 100755 index 0000000..2097e24 --- /dev/null +++ b/showcase/code-analysis/start_server.sh @@ -0,0 +1,2 @@ +#!/bin/bash +uvicorn app.main:app --reload --port 8000 From 57d9f69996f2cc90e98bb8cb2f201d1c63ed8858 Mon Sep 17 00:00:00 2001 From: Lachlan Date: Wed, 29 Jan 2025 17:40:08 -0800 Subject: [PATCH 06/34] images --- showcase/code-analysis/README.md | 6 ++++++ showcase/code-analysis/images/img1.png | Bin 0 -> 41991 bytes showcase/code-analysis/images/img2.png | Bin 0 -> 135371 bytes 3 files changed, 6 insertions(+) create mode 100644 showcase/code-analysis/images/img1.png create mode 100644 showcase/code-analysis/images/img2.png diff --git a/showcase/code-analysis/README.md b/showcase/code-analysis/README.md index f00ada9..b752b02 100644 --- a/showcase/code-analysis/README.md +++ b/showcase/code-analysis/README.md @@ -2,6 +2,12 @@ A Chrome extension that analyzes GitHub repositories for development patterns and metrics. +

+ + +

embed images/img1.png, and images/img2.png side by side: + + ## Features - Commit frequency analysis - Contributor activity tracking diff --git a/showcase/code-analysis/images/img1.png b/showcase/code-analysis/images/img1.png new file mode 100644 index 0000000000000000000000000000000000000000..825aa0a76e0805f39d3f353e5e3b88c7f0323eca GIT binary patch literal 41991 zcmeFZby!qQ8$XT+0wPFANH<6$-6-9luynJebl0w;^a2XfB_LhW4K7G`Hz){8Bh8ZE zgHOEA`~0r&|G(?{zI$C~&)GRMbI;r}bI%>0*)Rpkym8t)VC_O{3xJWM%sbjDn&N7N>)u`?7~P-QWc+8m5et(z+_% z2LdT2Opez_bfHQLsP70Yo@5c61Dy# zArTSoC!Ew9$34gAPBv2%AN6mxZ_08RAN8Q4&}ic2VXX!lhCW1nEr|8GLJTGJMR$t& zKrHLNU8sj8w^V4+Mt zj#1{Oxc1ZIykJ_M-c+-NbW3&Im*yU!k_w}AbhMNAP&zu=B%q8|R;I ze}QCt3{-La_BvVxKfAvJ)jUaoV7qLzOKA-JjOXfF)NS={y#@2rj;2tEKR*{Qr;Ik+ zcG&AB63Kq_En-EX{ktM`$hu!|4ButFmeSr8(qjmV*50p6=Npog<0r0-U6VP!Sh>zh zHDz?V=aMQW>1p~3LS>lB8qlPWOhS|wPRKR193oe+3_lHY{)&F*HTt73Id6JsutNbqy`koxa$+5zB9^yx@C20xnAioRUv>4-ehg?q47RL}ibS=!j ztFX8Cve5Ev9v&i)`~BTAq5!2BI3~eY!tT%;e0*wwJN>j60^plg1jh8<1B|CXu3+Y- za>M~&V@VYr&;;YX4XvrWv-{TX$B$p@7%9Aio#OWn&UV$km2Bw6=;mpv2zONoNP2^1 zgo&%9uRdL$f4NK>PiJDj@1YFzn8OG6uYl`?1 zJB?n9RfNI5Ej0PM+EhNy+qpx0!@%WkWyeuRERIKTY0{n-NKdi;W#r4eF%oT)bQ}Hj z1GArM@oEWSyiX5xDb70Z%DoBRtYF4h##XYS^zKD(9-lBZ>@@~*8??9`LNUHxcsn`m zeb_TxcR@L+Z`W!2v6qTN4$&V+5rXP|dcRsEWavZlRS<(xBH;WhY2sb-#AsgUyT)H1 zq6KQ;VJ%A$Bw}U{z1uRpmm8R5O2vZ8Xez9Gw-?Uzg-Gkof~jOahU#|)A#Bb!Y~SzI zVe6=4c;9J&i~f5243FTsG-;@Wd7v)cNhoidod0_%28ys}G4Hh)?tY-TZ^`tO`pGj8 z-D)@SXR?_P3OO}8lJ^2XaS!k|WQ^%EG#+TnduY&)-=_?#(8MJR?#v_{e&Bvz|23yn zLKfJDu>re8T0JXanA}G69CZhdk{is!^RoYrg@qwIfpX_4&tm~{woavTrD9_Hcc)0Q z$tVvqY8Se}uX=TN4dJxjVw_*|zE|!udJ7u|P5sE*w?C6^BEOOQg#Q5R1Wg?^nmg+K zvqU8px{m}kgt+*FU#$z?{)$pycp5e-<8{W)gkKrT8>$>i9_km$9P03`>l+n8*k|<$ zW}jF(MgJF61))_@RT1u~?s4PK&ZR)~Deu#Ip8d3}cxR}<$+*WrO>e>|Ne|7ndBOf9 z{i8zo`=@CYu!_i0g?g2ZPyV@fnk5B`<3e`C9#qvZePwa!X8C~Z++3^NwM^m?CQwQd zD7Qvur)gHYI(l<<({t1C_>o7@`HN%9P3G~v{MO778xWtQ{!@3gU{YW$g1N(Mu4s3=V8NQVy9Xs5>RIc~#WB+`+3xm8#o)V8phn&+@m*ZczJS(V!QgyI4yRq7cC)VR(vpC6~0&dUuMm8 zLYk+@OA&d@qimCN*bpIy!VXSJ%askNFH!e zwLs6Dg7Y)e%wRtrw3h^P1dGdc%E9GcWP8Zv!5Uymosdqw&Z5ZZ$6m?YD*h_pn2J=R zQZC`6U>9BC;-{0gpxS~=+t7kG_Xyjf4QpQeO7F_&mEu;X0|jfZ4&4tY)&|xVh?$5j zIIQ%?buXM7tdWbov#cX_ncB@0Zua8#=^k%9B9Fz%lOxLp9;GOyY}LpZ z)Hu}a+?!+b%ug#a$~6jF0Q-$E4j8{`g||4MnZ4`6>Jd+kO7B!JR+YW03r;E!AyX^;x$1~ewyY`!XrzJ-L zKdpC}kLGqyVHSNo%iGIMM_vaBNa_RV(DBc~<#f!isDXFG@9N*JzPoa_?=Cf35;_=d z0?h-X@!k-o1paeOENne|*9hxxgue=X7BY7;E1#=}6ohmH$AyUBufe#ej{K_GKLrz5)OgjJL^P5+ z5tfBIseNMp%%H{Gr2as`Flk!C@n@ah3Mb=ZhOk(&7{wl}p1D}RPK+oM-WK`}{v4Lo zHMA|PF($)A8*U!!#2(0@Ejvihl235e)T=@4>pxMR2fS;w30~eNU8=4JQa2DJft`j#$I#p z$4NKfj~3zbTPzDw3u41w8dOhRs{3jKpGS{|-oGx$RmfHVx!Y$>wW&t@l3kW9iIC?q zu01m-|8iy?_EOQdCxJ1LkpxP0>^3vhtUQ)b!|7&F<09-*Z;2crYGEq`*_E*CBE2W3 zwLOaTiXwDcjd*Pbf?gzys@fOW6WP!8we^ur>J=Nb>?-?MAtUeKgo|(COmP|CK;AmH zPeekYkc8pG(-8NF>^B0vyW;mJ*L^T%zTgf;>GF0JatVg66Hc_ z=ULy|t%p3gL{qdLV_OYdyjyeRF=Vs2AykfzM|NWF-}bwsn8tF$vm4|SD6^>yoQqGr z;rr=?ql8AxylN7T>Er&V<8?2m)a5fA#R)yvE@wVf<_)?GQcCUxv}^<-g4#)DNVd4@ zjSB5u9E6XGw#q{E7xcF{8%-SRmR)kn9aQGZi&}Kljj`)IPek_4bI9=pXB|72ngZBX zK^G1`b`V~!yG`dDH?>1vh(-E&ww5xV)}uE+-u5mzK$pgLCm}~>U)$s5%cFNCh{YiL zGS@$qy8`p7@^Xe$(zPYMAdBOV$9-0#_o41h?_191wU6>9Gqy}-o5ao%mP|MnRvJW& zdyJ1;j1S~)2BK;?ol^X=e5soH0#196yJF0 z@=*M4P9Zj_?={J!@7w$D`~5`$<02fat7xUFioyy!W1^tlAwxk2p6&pb#2xa#pXKhb zpxphPj*5a3VvBC)B@k--Ug;``7cGufRK$ zXD_7{6@mLp3s*4M(apxm-O66@wj`Fbf}R@+3NhpDbw}|9!!MxzNn0&lcU@H#5ep{= zPBTj1}A}?g*{wxms5~s6qcXt-y;_~wH;`HL>baJ)k;t>`W z=Hh~8DiNON1SnYojPyEq-)Eup_Z zf3y?qZTlZej&6T;3+N!%?Hev0PHwKh>jsL7-KL6Y*m{Fs>B-nS06YU|NbvCqiT%$1 z|9SHtivK97`=64+-2YYbA8-C$QriveD(&O|kaU;$&v5-o_Mb2REGWix+w*^L;tw|e zP6hZZabJwO%wRdg(55 zSpoxDvM^aNv*>6ln8GUvW$;vo_>&;^a!W{!}=O@@mS4Pe;mbJ>wR*7p41;itt`bJ$bVT7q^-oHs+nC z!iY%`^(ytb-0vE=L>`WrN0agQ7FSQ|*HCrfHA@FS;30?*@tmb46;(~W{Ie;)D;o|% z1Cc$QE*7gIMJ>{7QkOt}PU5qDL1tv`a?|M^DVK(SusC=Ef>o)?!1%aDu{oG(A}s%yHAHpT{i z_QVdbl{Ll4j$A&|yJYw|%Sgo^{lblfk(As+T)c#wV7|)qNHz<)XtNrM@tfU$G3-(7 z>vsw!Wklhg&r%%ASwQq0@cbYbtNui@MaabtySIr+#$$n3i66ek*2TWw-q}$NDVr31 zr)?M)k7mpEE}x6^>ah5iM=BpXX_}C`e1i40$gxvqn+MYQ-QOd7OKMi#^!-lXss4xj z%slCBYgrG12(Fg1tR!JKD?1OvI%l(&EDWsGp^*{1ZOmq26sXyzY3E*0&BbI zlwv}klwa=!oo1G%e1I|Z&;yNrh~d8rz6r#8Z)yl$)vgeyW+WbKrrrr1dDeGoQ7p>` zs^%7f=V!-dZkP*_1#b%Ed^GhxED^-}ztE4Iy$Kv+itNgVT29^RhE@ef`2aRp=r{9id&GIX_dq;JL#5#fU zn}{_o&PnI-j);M*qe?vZG`y3U?O!~P0|pFtgWOIsAXg{LrC!(lkaW)6OzTam>A1$Y zY##?KBA)#@H^`1-_t}5RPP}!RH(J~$xQZMwX-l(LTHI;@kixW7Qm<=@PO8R_0e!8}(FDx_cRK=}i_cpA!9WD$DiLa{eSb}fAiu0dHH}^ z)4NsH>bTo_1Ib?ToO7_AH1^v;jgO&w_GudJjEbl+fQ9leDSG#<6eC>dRh*esv&STl z`prsGVcf=y%{;NIYWh3FITmo->efzVcB^+_Dzu^-V)jr4W zWKiq}^z?o}S53U%JX2|%GNEI#P+ZVW$5HDo(Wgeju4@X? z1IInRAsSdobsOYiPWLv~t6uUyRIMCUVv9qrl$#TL_p36m@qM3J3<*o8ADqaJ}dT z9($TN9nEbR`))A04L`$}NbTtUKtG^wUjn|~S-KwBZa!VKir}cp7v{W^LO;B_r|Fin zbv=D^wRGcq~m9^3pJ;d5{I4GJz?pQ|~kQDFZ3C9X7$0qy0`r8zg`uG}crE*B+ zX;%QU$Z8}@mWdK%hhr5&<^P`lXX^X=avNDU{x?)3eC`%O1h5L0bm%p5jm-q9B+HVS zvUEOK+mDdE@fn+%B56nqZwn)2j$eq?{c!dxZP8dgLt^3d>2F($wuCW#Q8u5xxgA&Z zvl~;h>Bv~?)sBNxX`2RR>zw@Mows}9a_*U?`J3Zq#FRx^40)-~RU0a|Sf zJYbFMp_omJ=jf9pQ>{89Po#Qf`OeDqHexDXb*MY9vJF#CuOdohlf`X-f9mJsasTGM zmJ6~0$6cT*2*E!K^ey!H;ufW9$3 zvK{wYEH-toPjl^kvNrxw-6MfwPU_RbQntXOdi$91&3y&|e#)eV>*8 zl(v+866gCpuXw2#gWCU#xooalnq4RC@k^e5sfI993WX9`z26qoCu3AK?h~BH=4#?Q zDu-Q-yESw!NlFyWoi?Hj{5*$-oXq*T^BLz>pZBiTO#06!C2{#`c{&8W9&0*n-Yd~J#u>O-CTZ2>pO?aVZA!ty zAuIexd+|{TUg|;k4xUbGRc@^c-@@no? zWu(v9kC4Mf9HWSOrdj)?0gr77jcX@odaS`TQ9)JZi>1l)fOSuJo%4_9ycV6XBhmbc zR{PZ#*f&{{W7XqtxNnuIhBRRPW1KEJAvMNV={0timH+`YYIrrqmVnjS#he^X?dpvc zJ|HkRZU|kNm|2P}&1h%Qbnbj?{ZVQ-NG2n=&r2GWwQ-zRB?+_lF4JEfe0YQubE6 zj9YQXFS=W25f5r+KE5xP&@y|f(|R7)*dLW~_Kmq;9eO^tJu5kaeIKhg>3lFl!+E-LE02V3r_Zd1$RjB{KVy7n;g6HQ;g z;fg3aDn2e}xXzO}E~s#>iA@bEccbpx4e4FIe1#B+C?cE#@;HfxGMcd(iS2(Q1nrALIk~i@!gKur3LGqTJdaH@E|0vR&vSsGu@Wh-T}YJWtT2 zHTLA9KI!Kjdcc^1-0(9qk<(J`$|;!V|U-oV&)i6J8lc)Cg9rzVQ3} zz(5bmR`u3naxZwnkI#GPe$F@jjlk3K!8pU>tDX5ar4iP}$~GolVz%u-2VcNxsiUGU zDBY?9dY$V~x+Hu0Dk#b~YP)c7M68%m3`?9jv+8GF>mAS$`WW_pl{qiA--s*;dY_$6 z#6a6m^=;)ZrWDmB>EiXediKW;uc%tjH;Z}zAES=jEQztV8HlPCH&S8@LYDf+R>Xs; zkgZsxSgF_;InlLQ{}xx6UC;cYbhB0BvOAkm|JUM0r*%**y>?8R=ZrWHf0%4o?;RG> zk|6rCu9uXUjU!g;AdPiJn(!q<&rc8`vApps^bPZ z^z7;=^ggSl(S%3Oz!mZBrqfCum7t$8X-iEJSaSA{^M#`mNozn~zv045g(+JvC+Xt3 z?0icS@M+(C@4`tdy6eC}!)RM`;Wxf{-X$_M*+2zmhqL6Jhtw(L2N`br9HFbR81qYt zvmssUtmgrzV6)DXh2g_bh$;Q6-qAipiG9#ZgVnT_z6msI7IEYTy2he5AsF%rq^dSQFHkOMU=)+H!yt|0u8t%Wg^fLA zM6k`ekY0wZ#J%lb4W@M(^GzAX&wm;zaIdXQxR#JG`An(k#UZXvmon6!&IEW}to1C~ z|Fk$2;7}|B^b63GB&}Q7wt?Z4Ak?XIO+@`xi?$5~MAYBLtk3H~E4QnVO^~ zH|JAhrVqt_NpTOoKRX!1xiZ!^Cupz^Sv*(FZIfFTdQ?N)I^6x*E>IIaRD6ktEuZoQ zIeRvH{ourlMI|$TILi;a5O0jb;*Y_N)*-bG<~dzf=^HWc{!pFYK$vOZLOusSEo;S3 zOJ~~hTi&D^&x^F1>kOHRZG4V}Rlk~PjmR1FY|3)WSCXEDP`PTR)cSrvPaBswu9%(hx8i3Qu>Z%D^T~XB!$AI`V8MZ=imDD@wPe{!``-S>Wxx-26oAQU2H|?-Q2c< zNG?zMVj?5zuY4 z>yj~_*yO4F`as$|>#rG5JqO(E(cx4}@kXCK;rx>z`Ng?c4I8<(q8EaEUK&f}2)>Y) z*dT4!sCFhi+RJPM44NYe~2{ zk<`CU&?D+QwI#uetW;+sZwFHA%Vu>h_hp>~9@m!FZ|JltU|$~e@eXh{?$j6mQWFM= z<9?+rAak^^*E<;@9|tws#p6p#>g6A-j{f?lR7&Kuedx2<(2C$Le2`peDe9_s%&&5I zwi3-{@w1mpSy{Z)7(07$dalDX3u)rFQ>}O6$vV zad$ogIyJbbDY|JgKxRR*|0JoX;78xJM&~r1>cHdf#^LwvP1T~*d9&3-kH8LDOJq=? ze53I~c35%DE{-Kj^z>fb@k$*<)yo5+munSD9; zY=>W*SX_4vi?wiE#TZ%9QiXA?*7f`WP1iOEOWSEByr8d=k$`E?~;3WzU5p0 z=&O^YL4swp-*)zS+G}>$d826G^^VX=zgyv;+5G7ZWn$dS{m%Zj=?Uo<{D^_8XGhVK z&*R{~)T{EtMQExa+fR{tN1mSUaf-!v*QSa-9MWL|(G`(Tn_oI-_Yy6lT;O&hooLx2 zTemj$$%jwFVnrHV^X1h}KM1FiqHz$|9t=j$c9inq)-SL@LL`K+O{t3?hTh1Hbhd1$ zdpmW|^sdpo*4YAttLe2^`<3}==opY+{qU$)3DbKjxLd@a` z$!@?R+hq$A1^0e5t&8EXyTu2~VizeHs z`_-k(EYz?=k>Ig<$%i#F)*|s-*MBH8KBz6GO&7a7NiVkip- zx6Nd}WBjpMAIdQp106JPjfgXze+MbEq>QM4pY!tAp$by|bSo%w&yEOIK2Z^1-#CiH zp`z_@6ly{hwmj`Gb9&JAkeVDTQ#70S50B z11VU~eb+5RvgU%MIjrQ~V?SQ1Ez5Tzb_dejoPMd#o!S|F{YeZMwWY}{)adBHEt0U8 z*R?>4(6ZyFPtz9m*mYYpl8TVXw4+4RqY%gQ)nOkMy!s!dp6R+@ipkCmdOFx8Aru~= zMHA|%&rx3xR}XuVaW;Emb$U(!JK$hzsLL@nrF2AL_xVoauv3z^z>1~fgKC3rI});! zVu84?SoQBs#nwN)eg5oaYa+iW6KPyojq3+S13J|<_5PzdyxzHqN=-Nm6DQ7%4dT7E z$7ss5#$sG?fZoqlX0rY7d3%G0AQO_I-5Ih6d&?7UAM-!jcku4?cH#fA))HQGk?xU8 zW-`IO6RKrI@>*;CcB|FBoQljyD6y`2saXjrM)b)cVU}Jkbq$8fjM>1JU^$sn2b}8dx zt@nErkIN3bQF+BVvZ3nI!saZwcl%-F1b6%J;l?JhNbk8MEctft04hC zgS4U-6WK;ujAsSia;et;`~O z%F#}WE#0;i_NP*LgZ~SCr5<6V8*4g$9ni?o(y1x=xhUkb-QB}sYV}%6{}$x<2B_;r zJMNXbjpm(!t9_$Jkp|9a4U7Wvnu#xLHVv%zqBChN?8bZzRk#ar_!-6m%-u*jgc&AF zTd&W*9}@Yl6(Ws1XTW-K=7Buec)|rouzBZp9C(GDf&n9mfe>r!uV5LAelop+-4?L+ zs?F4CzR_{CN9hEzY@&l$+a-d{mMs=fy2E}v%#UTj_iEgjmc*Ahg$P!05F}$D4tA8| z?p$+i2+DbGQ1g?cgBElUTg|8S&}Dr6P2$-5Lyac6%c|ihL$>q{U7!7s+u+rkK?3K% zeIHSDt1*t60!41S#pRIey=zA7?;h2rumO@WYBPsGqatja`u?FSJ01C{IG*u4Tc1sj zPVoScioBl4A>~K?kk7%zDx5~Zymr+}#$N66K=8m5m*ypEUccMSCBgE^3sO8do~$nR zP3|JS*alon;8V*qXHEvvI7djVA21#Z*m1HE9^D25}C@R%^=uv%@nrw4Ni6`w`QM|KgIHj#)6bBOJvtD$3yZl}z+Siu&97o&8g4i%Y_Z62qPF&>G zwGHX{9SjN$&(_)Zc} zMn$|71kdNQpj6cxvWz)R3w93LGl&P2`|8E3 zmnCi8D%FsK4WISX!pCq@@_05mBoSEqb-f$n-qtkCRI7nDBE6;TaBTp4O{YgB|46HB zm;zKSpMws6q@&i#pIPJ9uAC55xVHonA3I)EviTjDwZQ;fmjlIMmz9AUR(zPJdZ%UB zjzxaP{&(qz)SK}* zJ-!0?nw_;lIBw{P61Ff_k48ui2+l&w1HHb~7!6yD2^pzOApQe2NO>I5LLhm0#b*8e0m7G5`nEh;txX={Ch5b~-||kf zuyYV)HGgueaM0t`wfpwP`VcM7e(6ujSvO;jd z{pFX5aoUJxq_!cHG>srXFPmKX^bH0TX1r{Arbv}EcjpOL?57C>za?8-?N>ql`smrZ zh3!ch^!c7H4j&~a=N=cza~DEr*#diM`t%|DSYcECNcR$?8f{*{_(!$t6|QSSLYUI& zqedFV#g2E0ZITDw^m@N^^(KS|4yPz&t9|kvuloqfNAV1AvVE*(W9awH-Hyj?Jxc-S ztmk-ZT-uff^0~vOAMXZ)s=e}!GQ5|=3VVWs5o{cK)BYsC*;e=}^XbJWm;1OyK_T!sjevkwU{542cLo5dNHx>` z`+44*cn#u`6L-d$wlY1n8ZYA8l>#+4STBKCN{WJwHreKr+?Kek7kZ4(`Pg5$X>&Cn zjk-q!`Y$Y0FC~csOn+O`b%A3#A<$ z#n(vMicCZkuy)yM(_Qw51F&QrJhBr=cs!9yyTe)f6YOuxOSlev>=ZovH&#t0ni?l< zq8fJ_ik7=FhKgn94GjS;@}8dl!l^cw@bSfFhzr7Ty`gum*IEPw{d21FqLJal<{Vos z6mNJabF?)XX0=@_F7E1b+odbevk5gw=3Z;2;kOd*CO4)>Ioj}xOFm3PAU1+TOm_%i z`Wo~m>Aq!KM6l}IjHTiE{WAAr9d6c=X$_ugX$YpntLciOm-##M;*@1|%i%H0I)pID zyb=OQTh+@@m0^;@cW~+K(RF1;ZW0$Cyn0?NaA1;2DI!jJA$1c#y%Ae zsF;P>I950ZlZLvyjsf1c1LtcX=3{}KUsr*YZ|=bLfB@>~ap=ox6Z*7OIkfEJyAbg! zH=H}iY3%8dp3~3M*58|IoyV~=Ly+!Ne&r)7det%3ko7_#Ey8|e1#+sw>b&%~XQXu^ zZHvqQ2lfa;ZT?`1EyIWdK^u`gIuSlvT{peVtJJ8834)Q{Yb3Yw`o=Vn;y? z*aT?^L9S}1#>sJO6~;o<{k+aO1rkQ02}Oq~8=!mQ42AQ;CZq z#SOk}B026tAIqNi)$}JJl`*ZvPe;DwB^Kpn7xD2`mA`-h-PCT;7quo6AtzWyMwNgr zu_wIFk2d)Aa4n7U`MxQGqw0YUkA~x9YKi+7CAMvf2nh0PIU#$(3vj&`gV3@`i?SaR zAdpAeQB6eSL({@7ZGUz1b`A7m$)-Xp!jDgvfO!k>cS4 zi>dMi8Ume6;kC;oXimQ zec-As%8S~;gDL48#%=kyWWV)Z5&2J#;faw?tCwAX;9#jwRfV<9 zP_YI=x{X6JV;C^$_-{C=O`uI|!W`~&_Sy>0wj=kJg5CudD^xd3*PvRb`&jW|c`!Xk z7N!$W%(}{O@@e(&&>{$0zXxLXp0QAt$P^7B5gF7JQF)jACZib-5u?S&q;n=be9$p< z-Wrtmy(Ldq)6n8XswUD)-r|a|RC^;<8n+Tn#{(RQvaje5hmuQ=DGJ6o(i z(dNg|+PhS!*mGL0`*^NS$gNdmbrAowIX&&3$ksld>PFWQydgDE>06~1?Ih-Lv9;%) zkV{*8+~9thJzGabV(?z6Js=JH%JD3Myxw^?A2G=lEBdhc^H^^=87etJj&FIMPy0D; z-L2^P_|k`s@}_0*I4yt8yfrVpEFmT?)i`GLu=rG@YC8I0oX%$Q|01wC zi3N}61-=D|3bzQgxUV~)Z|(W&ROfpv=`1){v-a5o!FFEzvgVq{V&2XRw#Qy*Yyy!x zb;$|FzE2!px>P>@4d~77fiRqMd6TX?b_nJshu5~3_E>fxW?)lF4yG9_wJwWBR zjo;tvXkadJQXY-I=h6Fe>F$-$*j{wHQ^4M&o;779{2qBCfF@{u*+E17#~QXq9Wzd} zlBhd{FcJBkWPrQCqg*2s6=Q`thMDLV+9GJLr6lq4Ww}qJ%eyP?qTz~eb6b?i!&A54 zOIIFG8er`Gm=Q+xeOv*UX(>Ii%n9H^5_Vstko)>@g`fAIU~3Uo6!^65@=uI6xcE}s zo|x`;Dn4K~?bOV@*xIMQ{uMHAN5L9Txt17=z0h8Eg|-cP-Z{9#YsV$ZF!_%CD{GL^ zow;db%MKTw@Shdh(Y!V-zC-Yg2EbC#kYbn@@q?^HYp13;I11$^oh@;cJC7f}xj8Sp zdFq+bAD%Q`qQJA^xr1gA@rGEaUMX;-l*NAAlh7)J z(v!s*2L#K~2B3)4FWi0vk&uPSQTzcy`J{k`2a~nK=|z1*OmKFXag$ogy~!*Lpvo%& zoXMGSs@I)20G>s{2mY!? zjt+X8=>H4)s+ItlBldkSxc)^}6-XDrdcXch^aF>p-k$FN<2=(k6)@HB%^d&$p1dS(v%n+)hvX!2 zzZ##Z#zimyXS48J3h)9>tZnfnvW^tuCyIF3^C4ZlO{$07Uj85(&hIO|1r! z!KL+UWVeck78|7Ff~)ni!e`HKDJ9tF7aU_?y4->-*lBg3b_p_<3OV0c0|L!_gv@Fx zvFUuaF#y_aF&0dJQwBLMdU7*m>^DH+F|N4=V7-QRFPO_(&I^;Cg2P8{kwj2dsjG`? zWLpq+WQ)3Mp_`La88qb&+wnKz^bLgJHf%oIms?vlbTl*c3Eph=g_rYaI*_sR=;-Kk zhEm72&q|4`fX#dl>j%iAZ|Ph{4em46Jp`4``*fAwBj)xa3jK*5UEc_wd`)A{@E`Tx zP&RoAwA-(W4}-$_HS(mk)nO9A>e`Sxj>}7#Z%$i8^8xQ7YRiBva&rs;E4gy$I64UhRs4bus0BkPdiu4 z2Tpmd*%}#r8VcBTTZ>WVbV*?B;)3i)tYt-TDqZb1pBh&J2+oi5r(6tCK+7)1mD@Dw zDE@ICPU8VEup+ZRfRKOMjMq|teRwABsYC68mFK)mS8^L6i<%Ujd0F$x(^zJ8wYycirlHm%&~rz z_;4f|QpM2G{!nthTZBF@GlHw>*K^-eDBq>VhLE5|=L24^-T9*zE3Xexk7uki_?5Tu zjO&4;k0}6PS+qI6)ot@EnnHLqU+flK7l~F>EK5)gASRvRf$~@-dFj5aX|cj~gtHRja*`dk$GMmVGtSgVs2?vjKB7a-suYU&2;y3#@f?Gzm(gUCcHzJ z&t!0*c5GN12dnfaLyVSuTr&tUYjr%KGn6&XN{SfD$iRi4tXPGyONQYnY8!0M=vhSa z7e?U><>~cR5AAN`W#A5`T>^+whg+OrlDhvg;aZ;Lm2HP5fNS~c?)@t>gv!nln2uH3 zz_Kh62Eu)T`*^Tt?B2g|I=`Ku&+!1WnlHIscjNFp1v?hqsVS~0cWBFrscg{XebZAf zE6*p_3bwC9yQS&t(cagGRpI$ zb;u&6|1UV>kCI`9;!i!7+sl%Sn#C*%oK3&lWPWVAi0(DHCFhRTL||*fe1UVc)<}al zAmT~=7J^0%W%D3kGBuUrP{nQMo^SW}D}Eh(As+k*0G8MaQhHtC=p+nI&BvfDzHhyQ zX6zA8Is~eN5*OPsbpTY+$n~IynHkib5TxTLy6bsu>N=(>$O!sk4QV(9u)7jIfc4e8 z%&Hove2iTW_&V8|%Nj&ayXm7pLrQU#Ob|-))DuJZza7oTDa(7A>?C=4-uYDA1if6L z2K-|@%{9{DhtDdv0Ju9%ghdFo^>yl>ChM&tawK`jmd}>oR=`%!R>)S^R>W4+R?N0p zNuS$jFIWHd8+Otm0G(GXU4&anXkWe-t9u|i?TJ3Xx8CG)sB{@EcF@g^6^1PtH5h<@ z01SM=&lY7~E>gx{2ODQop8GNE>S+q^X3#BIJ4XWSKd^-*kiZC@LnK;Et0r?|{2q!Q zX(;NKW1IL-(|#y7O=^`nUWt}Whb;OZ4)mKa>lpih6(3(#Y>LHSKgmlah-Btj9o?Vn z1z!Tle5S^|w)*UMDb*~EpEgEFV7Gp3zS8MgB6HlL^vUvyFZ+^|eFq#K?YO#+1vrhxpsL`lJh( zVfOd-t(4@S_Y3QNzZ|R^1gpC4`Yl};_XLRg^EAhiz<R zg!BUEt3@HJY$h&>Or9<=3|vRsm(}B0@g(m&clE=FIH5~9W!c}}zYBKrlrT^f-VRUQ z1$AU|F%YfyAg#qv#+v?rm-_$r5$=N-W3%5E9XJi>*~V74|T%tZ>0 zb3bi8sV-ym%y(pM*a_rG(tfeLNK(^cs%5B0aw|5N-PZaQEpe)(9V+<_QETzxHnpP) zsokF7>O;bplA;K1Syr~}w&@=^wu_$K9=;rs%|E+EPsQpFdR({C+r>;srkt$VVNv(x z|2BVrZxCd&v`#!9hx30j+&9E9l!qpMPqI$eb5%!`8FYN6v0Uce^65yn=-oRvTDW%? zrPt?L@Q)sZwT_R6CZXQ>rK{c9r#-%=iB=~BlU40upe8Zn>K3~R0sWxuS#CyDaPZ_Z z;BYNAixd%@2Ztb(Yl?=fR>N=}$7>sTjJlD!5pto+37W$}8fPab@zWpzNzcu(r5db9n8*_%z^>zPe@EE2^>IW65kLObZ z>6a#cX|x4)oF=6CE9B(*h~$&&i@hO{!TV092)EjpOYuey8Q-B=T_kem3S;cT^H~DB zs>!>b=-KS=TKqP05-Pk|`-lx*eOMSA^3c*J(AtfS_5%+1gIxlCWV!F4O3gH1hK*MG zT{5z!9JpsarRIe0JOl?^BN2zS_6;Co)(nZ3{6l(W%tmfC?w<3_%k9Nz$ggcf^P!;q zv6GSxWM&g*g}sFyUD_eKg-u;vo2^7a-^=!oX>5U}w~+Y{@v6jDH$iWT<4gNRhD6aU z(lMw0GxLQ2EQye9Zo3BBr846V2BFySj`MbDNz8mA82*`#4B+1w5;6oCRtgappu z-)<49a!f5k7?<9N&_a0Um zHv8poVR~m{YN8zbBz3~Obt?oV&KqdKQU8a%uZ)WF``R`@1w;gdL68t7q?K+YB?Y8A zq`Mmg1*DPgl<7`|N#P zdtW#5=eGvE@5?!!+9uj|Ua*w_^HVcbo}-d@H<(({aNn~0rqISR z%iR&j;8U$dm0PMK4pR6I#|+hp4G8R!<-RGD)L^St&hE%*zocc{`YQz0Ptg5_nRYjHzv1L-g!UsBOBI$=2j@JX?IVhj z_cTtGW`*DmOf3Kt=ij@4=mt=BqRZyos5kUeg!4gPkgvG}MoOfR!aCFn^PJ7ID5`lN zmz-MgvItlwf2p^dJA?7^{UaDi75uFx8{c9H7M}HZX^D`Qq4|4UGw+H+HQv3#8sMVo zN5Rf<)nUySfi05XAq`Y&1iBL@GD&O&q6_JsyB$nF_VXLbFI3SBGjFHZp5F}V0~ zHB)K81E{jj!J`vCYoKD5;k7OcUFnBXo%^p+=$e{|q5|HX_JFkMlJUdvj5UhC#fr5z zSg5e9iM<~PQ|Hw7_P#hb`NGV5#=@iVuWE(R^E+(xL{mS9Nbeljl7y8(J#Q ztbFe~AmebEu(6FCtYi_Lpm8eTbW zurJgM*uGk%3DHN`7wYGjq?_nz|^SCb!F_p?N^>8nzL?4TIT<|$<;Vd7NeDmhA z!p_>i2PA0IygPx3_532zHx`&Yi%NE5JytRUUo_#B{fC~8?;I+%*yw*NK9L#9qiK}L zF+e)B8B`G$Ym`nU{k^3v>0Y$w>$Vf|8(SsZz}%yF!FKjC9FNJd{X(MAyfQ_3gLFqtK}Gwr&M6ks}1sb0Nu6;&kbdC zb#)m``*eFhYL~-{AxlZmCiF7i<<+?7_9h&cG#-w_gJDAXip*ZU#k8EkMV0r4mMf}N zwElx)*uU*-#w^3Sx74ifeio3BS&PH>%{&zWd;dM-W$mTa8JxdXe(lNnn~oA&zY4s& ze`B62w}9R~=H3*;rJhuiFzQC*n%S@2&=I0Ay^R2P&b>cT!7pYZ=`jV&_2=Vswz4sW zkHk#%drZ8^(am;veiaY%TmP&41VtY2}RgoPvgQ^H>Z zt&b2YLYuz?zWUZy;4-Oo3~K8S&Vfl~`>=fPy-y4;7drAGTfKf*0fT~UZsX3Rq2Kv6G_iL zzV|0a{l|7fmjEEK;o~J9_UB^#1xxSW0f@E;y`{&0ndg)o`22F6)%@BaFEhWV#Q z9q+}(#f|7XR3#(WzOr|l+8-RCbGi?$oC|;aYi8Gc$({h%-$_?NX{KE{$-vmkEq1oL zfYX=2FxRh>q5Wl_2!Q)L><`b>_{*T~$pFa*_IS7a_k6R_>V;YE9hMe<*Wbt{m8tn_ z-i|RsCg_GDB8?;*T?}{N;m+4i{`$tg@{Ls7P-?yx3ML}fvyUpy^Ci&+}*U$<9)Q;}n!xv-2 zlI*!R{GOwKkp642FH(iLVQSlLvoo+TBevZlw=WQ>;r(; z)7Xm{sFY5f{q-ci3FGCYF+P|XEUS*Qa#OPMCq0MK32bEl0FqupD0rh_Kk z5eU%hlYvKk^(Z=u|K%Y8s^JK5uPR>-244$00gtljh#{^EeaH&80>Yy$pet4Rhh#bx z)_VJ=WSb@k6lhP4CPdY^TLW#2vZa>*1XaJZv}6l(L^wbf<8=js=07iEyqequyrOkM zPMm$^Jr|A*0Iu9R-|KZj0sBxOIOo;WYCGAkUuQbXCcnt1y#W4y9k>sZC!-TkJu}f3 z7u^DY)PnUVF+#~Ly8*#FDL{cG?ETA{i@|i{f;S4aAh?_hVV*qOZYF2=F3nIOYM=f` zCy7TKSn%s$DKtZ^?*Qn$)dLK!{JW)RGhq+8&$%5K&@`yyM7Vw>bsp2-0tzN+&7B+E z2LOP50R>TKxiY!OeG$S9<=w1~h60^VQ$Ukf3PTuxw`)MX-o0H#0)4rY#>rMoJwS0&){}G^vh?r_Qok zT?aM*b7BqjoNtbY=vfASR<*hN07ff)AkEyka8KZPhLS!DHawjV5$_^?*8hqq0RX3N zR_U4%{Nr}_$pCMTzA@;hP-^2cX(ti&W-k-K87*BpsN$aHvb%eJ z71~rZuhUXmH8q%}f(K+%xGKtlC)P^m?OPOAh`-!fEuV6pAjt7qF9BmFTUJW;^Dj;V z-4UD|YVB|;P&|J{?Ww^yv|dtL)b+ff1PiI6R(Z3Kxt4jYI+ z)dsrR#f(mr8L&`EsC61D#Yea4VCb9|b5(F}{vrwM)ugXK0ykfj*aAWqpeg)bNBR1? zrU{#7FNG+8k|?wV)I$gwj%n+4JN(C&N_x?my`xR?$!o_9LRtV_nIz3tALL%TA2@^H z{06zC!1jpd&%IqtWVX1qz~#&A8AfwSvKnbC@53J^SO_Pc$s=;E7kemA%e3OfNr>n! z%WxTBrj1TS^iE@&9UzV)Zf~B-J2eBIZDMhFI)P|qSx~MzWE6W?eaAceEgo|~y~)8~ zf9DQ42Btx-#qh+y%H)7dG6&-vHjLHDPNg`Sr$DfhNpI!C7GcG}6w2h_ck z0$iq)Ye5fOEQ}D+WSxNv|O|VE7U}pZ6*&ti62E)w~NmK89_R#-odJ}hFvM?v_}{1m7n<bw{ea_u^MLDsdro!6oVgCm8n#r(i{`bry9Q=L z#V{ql1j%%Igyy>_J|0Od`2IC^CXt&SHt4jSWy|oJB#TT}bNyJlaAa30K8@0`56 zO{x@AMvs;aHYPad`xaHKbQ`;JK9VpLs3(+yzIck3Czq=6ltM|x{pT^TP))RDqPghU zS%$X|H_R1`BJd#IMW3?H?bLZ9&_5B-+QrL(bk{{h>#;l6ORP6<_1g)omlgXqp~)~* z&w29n;@zVrqDql!+y)4ONOs0Y2X<|p@gKioj-;bVjcC)ZXs4JjyCDozi^e&t`4o{K zJLr11BpuyCoD~7S;eMMz@4&c1aif0&Z3Gj84mslnp8#F@k?Xh6H#`_t7qaRf6Bl9& zkh~ZBgAQH$Aw6n#v$Q*wPISShQ27Z)WDrf-tEg6|3YY$YHi_nP*(eDb?}{v7DdsUx z-w`Ya^@7LEiz3CzT{pbXIY}uekO~vA@ZDCsU#(Tw(9Ayp0id5wS!)YzrpZlQ-czbG zkyT=@T>mr%0pjCa^vqjrJ2OnAHb&Cljj)%DAeE5^T3&YXdY{AwJ1Y(OBBetpu^Fi7 z*lj}?4LjGTrZ+zM?`QOihNdNwr4%CT^QH|W_~T+8hXf9HgjcGy#W6v*LCli7Iq2Cr z{R*2SdvBc-BikN_qe72pd&j6P<{%lYN;J5eQCl(F`7Dmlt6le_Zok&tR><^P=C@PJ z?eNZ6=kkMLk%{g>-uW=?!F}rpS~P>K`ot&fx9>?as8lz zYu$!%OLv=CLy6QQF8nl-QlX$p{-Iq;!kUee)tes`%IZEOga)5-&jH6{ek@Nly9nB# zqkFR*flz3at}JZ7Fj-t3Bk)sj+Hq*csw7)$);_H>Brh4Nt!u7C%Vsz-hcaBk#YRut z;@+Owq^sqMoRckKbUKn<0h2dVQL9NNhb8V+5pN_ch&{=s7A2jJt>`!;)L!gGY};ms zhiMnN{`S!&5WGF@H-qK-MnfD=AX1xJOh&NsNbl0M2RQW$NCH7s;cnsa77$Jy+i@H; z|H44E-W6b#Wmz;JJ9`UqiTCjM?1)pPZPifhdB~g*e@!G6kurJJIGm}t(zdO)UualZ zKJtS6{n7DRiD)itcV1(ot^Z>F+SRCQVa2V zG}jE?mxvfE1VQh&`#tyGRxU+~hvuXuJ3Ea8-Ykj`c&oO82{X0MR>=(qIB1*QhU2Lo zywJGb57mgN;`^GEgO^^FT#I3s$??kfuF9%vQ1z`ZU+1A`V<$+F8sg4^^k3cL?|h=4 z&CP!}*pOSt(9AESSX8YigTul8P6i4|q}Muyn1SEqu=-{#x8Kylemc)%1zC(k4+6AP zrTks56`ikMSJyI*(~D6HAN+i~+P$__B?ZoqVg{pqZkENbZDPk-6y6!^zl_Z}DX-LY ztHVyd*$k1vz-5p^*4l11zvr5<1xEjv9p#`Nzy@L@G^6erASY&szI8GZQK2`W#a$!Y zLd`suGG496X0ZjdN+&0>6K30;8Nw2_Jm|kI<*q#m@kbDb9$u$iC&Id2GmL1oD22ca zbshIZZu$#^qK8kqbRGD2gXA=uHry&xa^43$$?3oS*-?I)p2?X!eEKU;R`Md1DiK_K z#6Z9B^`A99KkvW~#e=CBj|ZEo%oInEstEiB zs)b5`s%MqH`C&lERMB8mj-c#BhC`@eA^#=VzgjN_s={-=#M%6eZkoZ~Y$q3{!}FOj zd&!;K`}{cT#k{+;RtHa_(WaCjD8|0Kr-Nv&Di4Pz2mMG2T@XS*9lF|GbBYv@Wd=zzZ_@jmWyy~V=*_ckuc8S< zpX;i74+vIeJxgu0aSyH0+Bi48}x!U;s{Wf;aL0IE9Erw}SNTs=3xxsnjleqsNRy?Bq10 zZ#RRxqDkU~Pa*1rAFIEFfTkkRshBv|wXk}}GIV=o;#EuZ_)b@{L()zFmzY16W&6V@ zo*<{cMp%QTa~Q1Dm%(Bk-C8(~r%7gny7Ik8lcSRXCsGp>n_tfJ5_ zYgldbWzcCyaT1?{&~?VCM$^(=Lj6NA#JlspV^wHo7u#VrJ|jB7r7p8_o*vJF7RMO zL#=(9|9%P&#;b19;P+Y>R(;voT4e0UK|UyL8hg^R(j>xAb(O~b8%)OjZ0n!+d7T}q z0q04X69RO$iu=93sm|zVuw|u^Mrs(}-Gd3Q<~7|&vv3Lrg)5MLCzdbKi{T2Lcsf#n zE@_mfx>wEPxG;u`m91sInca%gftqaZ)F?WI?|refBdeij9=jp3L&2RUQMmios^>H) zY^(jI7k=oD*7$zaLFok4km+lMUZ^(re8ZAEX<3x{4#zf=b4LvqsdTr#k_S6E^ESxF z1;3fR(q5T(VW5N~ehusFXLKzgaS@V%X#O$)PDWJWVR=s0rd4vG4OnsKJF@gU<8bl* z+U*-xFxE7H^LTer9x;$@nEu4W5;v04+^v?-do*AjS3$rm7w?ot7;09OSp0}Xt=2a- zsA=C}UYX>80Yj67?O9nZ`ZJKy(Y|@!&KwnR*6gHj2WeOYhO1lKagX7D&x1ts#oV9cIM+@66gESbk!@z1BI4&wZ9ax>lv87u@!`eVaS;1K3Cu6C+P!7cr%< zw*+e6oPG2Q`jD3f@=bz$XTF5t3>rqFL3(RCSw3=_G@EQLjCW&;-{Xo#Gjy9>V_U2B zl#nPkiGhH5$2bmaYLwa8MMhBd#)@oniJxCuI?ef8x50ru;>oqVL-_kIYR4;yJJ*_s zVfhU^!R3YVX`~@)ITgN@bC$^Dt#uF>{KQXzzClBMHT#3CN@PtZVOIYPf^e!siex(a zPPIv^LmopIT0oFbcUg5t$+MW(T9pDEt(tFJLlRowyQ*6cKCTT1t`LD6D~ayp(}1>? z<4Ac<;8MjJ2rNh#sxie*YH-xMPnI^ay)(iRCy3~z^qyuw)H$`bm>Ma$SL28p#5qe3 z^P2laSH!X#m!KOAyiB`!X#E)kt~fh%xxc(g&s4C345)RI)q3qETIK8r)(ZulN!cji zjXu+NGt25!S`E=&Y@y2 z)g^)?vD`};J@N8l?^MGeQ=>JIN;;qMFqQYZ7$EF(C6}%|!;~^Ws}S76)!Z3^ z9)^vWW5YvRU8X}WCEL_4sqhE(zc3z_H0qjqLH`-l)iGX4NuR!jDs#d>!C(zPb3s4X zXs~s<{gryd!QOq4gZNW950y^$yrUNgAss@fYg%DzsA!m7jC6Wy>JrSHK$rf_4sccO zSnbR`!Oe)cTUl-v0%$QRr-(-RtFaVnZB7(K&~z5L7a>*BtEKZcN%EJ?aRksSKBmQHzf^ahy!lQ`*EBC z@b?x@L6A3avw`LK8b)VBZIpZ3g_C$qu(H|4t94*5@tB&`)Enizys4_0*}t0?p&rNG zZ6TW%QpWx>Oq-%aU`+zw+s>UATo1&`yC#i;ajzv}lhbT~BdSuTxcxdVR+jR)c9V9I zpbXn#t=@y=>YRx+Gl`25X@<6!))CZq8MRLnki1IXz}tGzv)3L%9g2E(JZK`&EhJp9 z;I0D2{BOuND*YHw->wc2&KL7dzW;@`4iTfEAAT}ssxn_O1ZE`1cGoTPRRRunLB>Y( zfSlOmLajH0sOu|3GUS<8zaUV>V80yN0W`#$@V%oy(i#@=VCoz&z3J4Ion1_&esj!K z8Z#$ETU|L9ExI^kX~e_`P7*?&>ep%%w-U+KnIuREZ7Z0R@=qy#tb)S}XUZ(8IXTqD zb`8rJOJHA|c#zZk^yxylnb8<)8(VF4u5|z5V+~K*Egbb@r4aywOO{L1>f#~N1n=`L zMhjK(uLEHOX5@kN4Q}t;-6FCIs!1~AJ^aN&`VdV^c4dLsXhMK|mS}vlTEC|KX}uER z5NihrD8SWQAdNI`Miwtg7KfRO5Sy6AGXV@;hg$TSe)4{THr_=7lxCTkW4lE!_FeF? z3XXSFoEz$5+KL*3RUfLu)Zo^o_L{XX3|$Pm%9@lt8{S2=J!@PHn@VRy0;r*ByC^wi zpGi$X^Rtv&=dhUB#`e=g>W|tTRa&_R2#tvYEeM7Q`eKdysv+o41aXK~FU2wfa1bJw z?a3tP+1kg?`~{C%G7m;4H*z_I>^*BTCs3cdToNvsLjJKnARypN4;BF@5X9F3&D)$o%uaJtH=>vCk@5_kyv!vL z@N_L;kW2yVa0{+DcY<5-r0d{t_|sBW8ifDAk%!l@QSAH_X(~vhhnW&D3#4WHk`oZo zD*jB`w2U6BX;D%Wyz8;E8V4xaW_j%RgS>h)*-}9|nSyh5QoY0R(bTf`?&O5(Z$Evh zjcPdMRh;ex%C`xQ8aoe4-Fh^;QbAVAi*I!J-(2Xbs)7(CjqhV`UBW0EP?g^nE4&9T zkQu>HF2MvBEQa!T$pHA#MYUby+L%69*lg4of9g@n<{FYc$Xoui1xqz4XZrJ=ia?$> zC|dt(z=1|%W4us)AfmC@WyI&BEpVS03oB><@U$3d)V(; zJBkqBhPn&hlYwu0TdFP7mp;$(&bi@N@gP;MbrAzD_drtRwUF>|Zo~9upL|L3) zlYeXBb$9fzsCDsi@Yc~O&vNdKentTBma;bh5GQzVs}&XhW08j{#ZOp6yWNgf5ygbP z|MdO?rI+eJ%q1|vUP2%O{M2nD3~@n;9#lazOsvi$O{xIE?QQTQ#T4Siu)HhCTxNW4 zk5m1rGf@Pt;b#~iAi7F zXXLl2@J-QqxCQPCLh&^n6%|h{9oTSB1DmX z&F^_S_Vd5EFY_e8IJwYt_+Q-DH=1{P-%UjBUd2?u{>(Rt8YrG#-OAhf>t}WWdS&m& z{l8z!kPCclQGaH}_t($-@6i9(>i@f8{>P4K^uxWi_A-dXG|{%s@r>9}|0p>mE|D>D zwGQL@ogpUQ)0YRT6Elv!0b;)nHbxH)pK#BMIQ`(+vooOd3iK6^a ze(0AS67sJp@J{(pn7^wfd+v<;LclK;iHqO5vVwaM;1BM)0?!dbJwX|@ z9ATk%ubk{Y9%=|b@4#QY`v_b`g(xRX{P5w`WLBsEm;Yi0=)1Z0&oqEWc{TPIFRm_z zK2!o|^yLXr*ELE&aUvh(@y*}9{gc|n0}I;qPJ-pPUD<(W4S)OghlyqeaHqKI)5(5z z?c^IXw?;Vwh!K0!XOkY$G_eI%+oCp&11i>~>PvSI-tga69CKX_n{07lRH~F5Ov;5Y z=gK;hdmm(;`9!BV$ui1P4dN_(6TfV-Ztiq0h1tkmo}V$-`N(8z5$VIL zGME*8)U>{MNV6bqKe10D4ZV|xw)}B)9DQ7W)-BXCr%slCWiRcy+}^VhaDh%&tLheN z^em_GUpHL5b~!z+8ke~HlQ#!#-j3uF#>hXdsG|s)f*?axAQ+^Abep}LWaCpbE^P};7a`d_E)pTyZo_kceqTm3Ay-mPYiZm7JM zBcj1Vcgcs$`#B4EJ!UUtaR$UUds%}^w2}9uQNA7BI9-t54C-NT;dv2_vAMMl&-x0o zqh~(W2KS{rdGEh1xXnK=aJ=^Zd-b9<+<}N5H#C_US}yY00O-jkm<=?Ffb z`a};|T-NPj@3!2)Gz!Zq^I%KH{@v^e#)udP)hb>QV6mSo16ojeB8!s zeNN)zpnHOYx!B^eq&~^Wd0FXucIN$wjDNKAdsoqNS^ZC(NtXcTC1Y|PsKx$#JYv!g%BqaH1|)JrxIY*mNm(^)d>5!l!9w$*@J{dp0B zgCXq(FaV0Q^O`>1kahVs6=)I%?lR})E)g!YZ4Ys&udjb87m}q!JOtmdIp>#Ty6)U} zxs?ui)t&c7z)3>TR_1=WWB{fdP!Cn%q}DsR7pDv27rU^_D4WL-FHv;V1>wPf!xIRl zUUX*Y_t_9{##t@%Iix=Fk+zET6uQGXu`BSiQ)Fw7riw8MFX*hK@%5*!;>F>@(q(>c zU{y3DCQ26a32YCFii)JSegrKIrk##GoHg{D3YpgR%HTrIMo-#|OioC)8lkJ}83idv zj!k+UXir{xo5=9GShigrWvfnN`0#T#1lHH;ZKo3kM3r+W6ds#(4^H+4WIi@y-=2%T zgusKh{-EgR}}2UD!|)jc6Gb zy0QT?Z*3hegeINgEEpEG4&fi6b#}2z`|*f@vqH_(3rU7N(WMfbcsHdYDLd*i$JhR-JN=MhnXBtPECH_!+nqZX3yOcSf`avuw zlNd&;Z;yE0D_8t=Rauz82d1*@`clAR_gJsuVCuoqutj=9n%YbZ3t_0FxDRC}=eLlJ zj)c5(s zkURZ@lW(^9NC(>d`p28s&3U0=aR`=YGy;%~0{Th*%SO&gp6xsz`#m@5w*?s-mrJ!? zQ+bFaQy4-J8Xkc!;PtiR#3y!8!jnv0zNttqp1-Csv(BWvl~J zSQ?k2LtfV8!uurY?p=%gC2`V_b)C9l zw;+NINoJj%eFMcggYZm;x+f#NY#(nK#dvI%dhaAjiEsn5sv#b#-Be2#a`#J&yA@9) zrY_I)2&zm-t9z~^_>XVTD#n!!l10}X{*d3k)bFP{%Y5EC z2HF=LyMjRd!wU{vu|R~w2YhmW?!cahqJ>&f1g)oBHV4sNl^-q;7D&2+=($)`O6kXG z5pJ8ToOPPxgyo+!ix~PtzVq{Z4mqQgW(g2Ql6$l(UG8UbdR+99Sx;>j<44gUgMD-t z{TIAmW|Z>nLJ@RO-CbnPw6@3P26tu4>(gB?aLbJ@|K@0`Ca6>8oNdl_R_w601e&4C zryQ-Tc&Hu~qulLJdk~t;R26i#SlE1reW0QG<`y4U!IVY_GU9A=ycuH@kAzq2tm|oy zoB@m|gfnEc0nF;{DODGfFus*EV#2t-OixzT-#?3N*Lk(!B)#sykRD!9^UUgc)pd{a z@0UA!>kBsuBH81&Bb{)hCSNe0FSl)Fj*{Iot3rPAe`7WHNYd}(3 zr+YFbAJr^7E{;H>n~$;v{GJm=$8kDudmYS=PU0S2Fp0KpWhA{mT@U4sJv%)zm%a3U z=6Qb5o@vd~tnbm>oNK~7`lfq2^!oPYjw zv+SN_42MNp>C%!;<$+j-gfD)hMd4B|-Pl>4gF27VPN;}#Q-~cTm0NM zwBQ_s=5SMxD=(u;r%BsbD5C0ygTGu5$O&k9c`Ev~ma zsp#4eq!Cyx0bW+$-{E$C&y)nGh85`gB2?_YgxXJZ2~V5vkTAx5wnfC5Ku?U5nN#u@ z(`IuoB~%ow<|#qLW2Z;)>AER(y;A39P5KS4k-Mw&Vvl$ziBu0AUPq`k50CS&c1do5 z!Q}Tri78!$5Cq=(hjj^RzO`lT+WKC&Uw;Bs;<(%fX}^&PqRkOP+9=NA9P{W;o$m?? zZF$k^A;n@YUj}RRpPsr5WLfSkbvj?fahB1dr;<5@&S!A(sLfWdgb5?a-l>K*veh}6 z-m*r1=?<@09jz2%sn zO{!Zi@q8!oku#zcSK$MwPZ3)BY&t_)R&) zw?fbJbn3D$n%t}gFKnsgT2vO)4lOZ-yFayDTM4im9lE^5Wyd3pb+hx2ocqW5IeV2eqbBM zQJnnQhR;xD{0x{8Y24j-E)``FUm$C@pT@bZU41NJsUHI^n3NlwebL+(s`5z&>keZ| z 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 Date: Wed, 29 Jan 2025 17:43:04 -0800 Subject: [PATCH 07/34] clean up images --- showcase/code-analysis/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/showcase/code-analysis/README.md b/showcase/code-analysis/README.md index b752b02..8f34567 100644 --- a/showcase/code-analysis/README.md +++ b/showcase/code-analysis/README.md @@ -1,11 +1,11 @@ # GitHub Repository Analyzer -A Chrome extension that analyzes GitHub repositories for development patterns and metrics. +A Chrome extension that analyzes GitHub repositories for development patterns and metrics!

-

embed images/img1.png, and images/img2.png side by side: +

## Features From 948e284bee5bb894cee3c300a659bc1776b8dec2 Mon Sep 17 00:00:00 2001 From: brandon chen <9735006+brandonkachen@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:24:23 -0800 Subject: [PATCH 08/34] Update README.md --- showcase/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/showcase/README.md b/showcase/README.md index 2ebcc4e..b8227a8 100644 --- a/showcase/README.md +++ b/showcase/README.md @@ -8,6 +8,8 @@ Community showcase of projects built by Codebuff - [Bayes](https://github.com/narthur/bayes) - A web application for applying Bayesian reasoning to everyday life - [Maze Generator](https://github.com/narthur/maze-gen) - A maze generation visualization built with TypeScript - [Codebuff Tricks](https://github.com/narthur/codebuff-tricks) - A community-built wizard to help you set up new projects with Codebuff +- Minecraft simple - A basic version of Minecraft running in the browser! +- Code Analysis - A project by [Lachlan Gray](https://github.com/LachlanGray) to show interesting stats on any Github repo ## Cloning From 408f9bdbad1e626e260ad3ae1186862b97148628 Mon Sep 17 00:00:00 2001 From: brandon chen <9735006+brandonkachen@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:34:12 -0800 Subject: [PATCH 09/34] Update README.md --- showcase/minecraft-simple/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/showcase/minecraft-simple/README.md b/showcase/minecraft-simple/README.md index 3c290ff..85bc1e6 100644 --- a/showcase/minecraft-simple/README.md +++ b/showcase/minecraft-simple/README.md @@ -1,6 +1,7 @@ # Simple Minecraft Clone A simple 3D Minecraft-style game built with Three.js. +![minecraft gif](https://github.com/user-attachments/assets/e1a5e6f5-a38a-42c2-955c-fa6de86750ec) ## Get this project From f8abdf0a98b67b095817a0050041b041d2a3bf2d Mon Sep 17 00:00:00 2001 From: Brandon Chen Date: Thu, 30 Jan 2025 12:49:16 -0800 Subject: [PATCH 10/34] feat: added fishies repo to showcase --- showcase/README.md | 2 + showcase/fishies/.gitignore | 38 + showcase/fishies/README.md | 22 + showcase/fishies/eslint.config.js | 28 + showcase/fishies/index.html | 13 + showcase/fishies/knowledge.md | 57 + showcase/fishies/package-lock.json | 3007 +++++++++++++++++ showcase/fishies/package.json | 30 + showcase/fishies/public/vite.svg | 1 + showcase/fishies/src/App.css | 25 + showcase/fishies/src/App.tsx | 12 + showcase/fishies/src/assets/react.svg | 1 + showcase/fishies/src/components/Fish.tsx | 31 + showcase/fishies/src/components/FishTank.tsx | 267 ++ showcase/fishies/src/components/Shark.tsx | 24 + .../fishies/src/components/WhaleShark.tsx | 24 + showcase/fishies/src/index.css | 32 + showcase/fishies/src/main.tsx | 10 + showcase/fishies/src/vite-env.d.ts | 1 + showcase/fishies/tsconfig.app.json | 26 + showcase/fishies/tsconfig.json | 7 + showcase/fishies/tsconfig.node.json | 24 + showcase/fishies/vite.config.ts | 7 + 23 files changed, 3689 insertions(+) create mode 100644 showcase/fishies/.gitignore create mode 100644 showcase/fishies/README.md create mode 100644 showcase/fishies/eslint.config.js create mode 100644 showcase/fishies/index.html create mode 100644 showcase/fishies/knowledge.md create mode 100644 showcase/fishies/package-lock.json create mode 100644 showcase/fishies/package.json create mode 100644 showcase/fishies/public/vite.svg create mode 100644 showcase/fishies/src/App.css create mode 100644 showcase/fishies/src/App.tsx create mode 100644 showcase/fishies/src/assets/react.svg create mode 100644 showcase/fishies/src/components/Fish.tsx create mode 100644 showcase/fishies/src/components/FishTank.tsx create mode 100644 showcase/fishies/src/components/Shark.tsx create mode 100644 showcase/fishies/src/components/WhaleShark.tsx create mode 100644 showcase/fishies/src/index.css create mode 100644 showcase/fishies/src/main.tsx create mode 100644 showcase/fishies/src/vite-env.d.ts create mode 100644 showcase/fishies/tsconfig.app.json create mode 100644 showcase/fishies/tsconfig.json create mode 100644 showcase/fishies/tsconfig.node.json create mode 100644 showcase/fishies/vite.config.ts diff --git a/showcase/README.md b/showcase/README.md index b8227a8..42ed18a 100644 --- a/showcase/README.md +++ b/showcase/README.md @@ -1,4 +1,5 @@ # showcase + Community showcase of projects built by Codebuff ## Projects @@ -9,6 +10,7 @@ Community showcase of projects built by Codebuff - [Maze Generator](https://github.com/narthur/maze-gen) - A maze generation visualization built with TypeScript - [Codebuff Tricks](https://github.com/narthur/codebuff-tricks) - A community-built wizard to help you set up new projects with Codebuff - Minecraft simple - A basic version of Minecraft running in the browser! +- Fishies - An aquarium with various fishies - Code Analysis - A project by [Lachlan Gray](https://github.com/LachlanGray) to show interesting stats on any Github repo ## Cloning diff --git a/showcase/fishies/.gitignore b/showcase/fishies/.gitignore new file mode 100644 index 0000000..e5a7e22 --- /dev/null +++ b/showcase/fishies/.gitignore @@ -0,0 +1,38 @@ +# Dependencies +node_modules +.pnp +.pnp.js + +# Production build +dist +build + +# Testing +coverage + +# Environment +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# TypeScript +*.tsbuildinfo diff --git a/showcase/fishies/README.md b/showcase/fishies/README.md new file mode 100644 index 0000000..bc5847a --- /dev/null +++ b/showcase/fishies/README.md @@ -0,0 +1,22 @@ +# Vite + React Template + +A minimal React + TypeScript starter template using [Vite](https://vitejs.dev/) for fast development and building. + +## Getting Started + +```bash +codebuff --create vite my-app + +# In another terminal window: +npm run dev +``` + +## Available Scripts +- `npm run dev` - Start development server +- `npm run build` - Build for production +- `npm run lint` - Run ESLint +- `npm run preview` - Preview production build locally + +## Learn More +- [Vite Documentation](https://vitejs.dev/) +- [React Documentation](https://react.dev/) diff --git a/showcase/fishies/eslint.config.js b/showcase/fishies/eslint.config.js new file mode 100644 index 0000000..092408a --- /dev/null +++ b/showcase/fishies/eslint.config.js @@ -0,0 +1,28 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +) diff --git a/showcase/fishies/index.html b/showcase/fishies/index.html new file mode 100644 index 0000000..e4b78ea --- /dev/null +++ b/showcase/fishies/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/showcase/fishies/knowledge.md b/showcase/fishies/knowledge.md new file mode 100644 index 0000000..fc36144 --- /dev/null +++ b/showcase/fishies/knowledge.md @@ -0,0 +1,57 @@ +# Vite + React Template Knowledge + +## Project Overview +A fish tank simulation with swimming fish, predator behavior, and interactive elements. + +## Key Features +- Fish swim with natural movement patterns +- Fish speed up to escape when predators are nearby +- Predators chase nearest prey +- Collision detection between creatures +- Death animations for caught fish + +## Animation Guidelines +- Use CSS transitions for smooth movement +- Use 3D transforms for depth: + - Container needs perspective: 2000px + - Container needs transform-style: preserve-3d + - Fish: ±200px depth, fast cycle + - Shark: ±300px depth, medium cycle + - Whale shark: ±400px depth, slow cycle +- Scale with depth for more dramatic effect: + - Fish: ±10% scale + - Shark: ±15% scale + - Whale shark: ±20% scale +- Use rotateY instead of scaleX for direction changes +- Remove transitions for immediate reactions to events +- Add depth to environment: + - Use transparent gradient layers in background + - Animate container with subtle 3D movement + - Create parallax effect with container animation +- Death animation sequence: + 1. Fish straightens out when shark attacks + 2. When shark moves away, fish flips upside down + 3. After 500ms, transforms to skull (☠️) and starts fading + 4. Completes fade out over next 500ms +- Scale emojis for different creature sizes + +## Combat Mechanics +- Shark must be moving towards fish to attack (within 30px range) +- Fish speed increases based on distance to shark using quadratic easing +- Whale shark protects fish by pushing shark away when nearby + +## Game Balance +- Base fish speed: 0.5 units (slow peaceful swimming) +- Shark speed: 3 units (fast predator) +- Whale shark speed: 4 units (fast enough to catch shark) +- Fish speed multiplier: gradually increases up to 2x within 200px of shark +- Protection distances: + - Shark catching fish: 15px (must be within 15 degrees of directly facing fish) + - Whale shark slaps shark away 250px when within 100px range + +## Verifying changes +After every change, run: +```bash +npm run lint && npm run typecheck +``` +This will check for lint issues and type errors. diff --git a/showcase/fishies/package-lock.json b/showcase/fishies/package-lock.json new file mode 100644 index 0000000..151f8a1 --- /dev/null +++ b/showcase/fishies/package-lock.json @@ -0,0 +1,3007 @@ +{ + "name": "vite", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vite", + "version": "0.0.0", + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.17.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.16", + "globals": "^15.14.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.18.2", + "vite": "^6.0.5" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", + "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.7", + "@babel/parser": "^7.26.7", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.26.7", + "@babel/types": "^7.26.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz", + "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", + "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.26.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", + "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.7", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", + "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.5", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "dev": true, + "dependencies": { + "@eslint/core": "^0.10.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.0.tgz", + "integrity": "sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.0.tgz", + "integrity": "sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.0.tgz", + "integrity": "sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.0.tgz", + "integrity": "sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.0.tgz", + "integrity": "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.0.tgz", + "integrity": "sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.0.tgz", + "integrity": "sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.0.tgz", + "integrity": "sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.0.tgz", + "integrity": "sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.0.tgz", + "integrity": "sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.0.tgz", + "integrity": "sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.0.tgz", + "integrity": "sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.0.tgz", + "integrity": "sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.0.tgz", + "integrity": "sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.0.tgz", + "integrity": "sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.0.tgz", + "integrity": "sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.0.tgz", + "integrity": "sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.0.tgz", + "integrity": "sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.0.tgz", + "integrity": "sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", + "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "dev": true, + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz", + "integrity": "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/type-utils": "8.21.0", + "@typescript-eslint/utils": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.21.0.tgz", + "integrity": "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/typescript-estree": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", + "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz", + "integrity": "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.21.0", + "@typescript-eslint/utils": "8.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", + "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", + "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz", + "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/typescript-estree": "8.21.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", + "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.21.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", + "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "dev": true, + "dependencies": { + "@babel/core": "^7.26.0", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001695", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", + "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.88", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.88.tgz", + "integrity": "sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.10.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.19.0", + "@eslint/plugin-kit": "^0.2.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", + "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.18.tgz", + "integrity": "sha512-IRGEoFn3OKalm3hjfolEWGqoF/jPqeEYFp+C8B0WMzwGwBMvlRDQd06kghDhF0C61uJ6WfSDhEZE/sAQjduKgw==", + "dev": true, + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.0.tgz", + "integrity": "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.32.0", + "@rollup/rollup-android-arm64": "4.32.0", + "@rollup/rollup-darwin-arm64": "4.32.0", + "@rollup/rollup-darwin-x64": "4.32.0", + "@rollup/rollup-freebsd-arm64": "4.32.0", + "@rollup/rollup-freebsd-x64": "4.32.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.32.0", + "@rollup/rollup-linux-arm-musleabihf": "4.32.0", + "@rollup/rollup-linux-arm64-gnu": "4.32.0", + "@rollup/rollup-linux-arm64-musl": "4.32.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.32.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0", + "@rollup/rollup-linux-riscv64-gnu": "4.32.0", + "@rollup/rollup-linux-s390x-gnu": "4.32.0", + "@rollup/rollup-linux-x64-gnu": "4.32.0", + "@rollup/rollup-linux-x64-musl": "4.32.0", + "@rollup/rollup-win32-arm64-msvc": "4.32.0", + "@rollup/rollup-win32-ia32-msvc": "4.32.0", + "@rollup/rollup-win32-x64-msvc": "4.32.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "dev": true, + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.21.0.tgz", + "integrity": "sha512-txEKYY4XMKwPXxNkN8+AxAdX6iIJAPiJbHE/FpQccs/sxw8Lf26kqwC3cn0xkHlW8kEbLhkhCsjWuMveaY9Rxw==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.21.0", + "@typescript-eslint/parser": "8.21.0", + "@typescript-eslint/utils": "8.21.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "dev": true, + "dependencies": { + "esbuild": "^0.24.2", + "postcss": "^8.4.49", + "rollup": "^4.23.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/showcase/fishies/package.json b/showcase/fishies/package.json new file mode 100644 index 0000000..b644761 --- /dev/null +++ b/showcase/fishies/package.json @@ -0,0 +1,30 @@ +{ + "name": "vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview", + "typecheck": "tsc -b" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.17.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.16", + "globals": "^15.14.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.18.2", + "vite": "^6.0.5" + } +} diff --git a/showcase/fishies/public/vite.svg b/showcase/fishies/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/showcase/fishies/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/showcase/fishies/src/App.css b/showcase/fishies/src/App.css new file mode 100644 index 0000000..35542a2 --- /dev/null +++ b/showcase/fishies/src/App.css @@ -0,0 +1,25 @@ +.app { + width: 100vw; + height: 100vh; + overflow: hidden; + background: linear-gradient(180deg, + #87CEEB 0%, + rgba(135, 206, 235, 0.8) 20%, + rgba(30, 144, 255, 0.9) 60%, + #1E90FF 100% + ); + perspective: 2000px; + transform-style: preserve-3d; +} + +.fish-tank { + width: 100%; + height: 100%; + position: relative; + animation: tank-depth 20s infinite ease-in-out; +} + +@keyframes tank-depth { + 0%, 100% { transform: translate3d(0, 0, 0); } + 50% { transform: translate3d(50px, 30px, -200px); } +} diff --git a/showcase/fishies/src/App.tsx b/showcase/fishies/src/App.tsx new file mode 100644 index 0000000..17083f9 --- /dev/null +++ b/showcase/fishies/src/App.tsx @@ -0,0 +1,12 @@ +import { FishTank } from './components/FishTank' +import './App.css' + +function App() { + return ( +
+ +
+ ) +} + +export default App diff --git a/showcase/fishies/src/assets/react.svg b/showcase/fishies/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/showcase/fishies/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/showcase/fishies/src/components/Fish.tsx b/showcase/fishies/src/components/Fish.tsx new file mode 100644 index 0000000..51e5ced --- /dev/null +++ b/showcase/fishies/src/components/Fish.tsx @@ -0,0 +1,31 @@ +import { CSSProperties } from 'react' + +interface FishProps { + x: number + y: number + direction: number + color: string + isDying?: boolean + dyingStartTime?: number + isBeingEaten?: boolean +} + +export const Fish: React.FC = ({ x, y, direction, color, isDying, dyingStartTime, isBeingEaten }) => { + const style: CSSProperties = { + position: 'absolute', + left: `${x}px`, + top: `${y}px`, + transform: ` + translate3d(0, 0, ${Math.sin(Date.now() / 1000) * 200}px) + rotateY(${direction > 0 ? 0 : 180}deg) + ${isDying ? 'rotateZ(180deg)' : isBeingEaten ? 'rotateZ(0deg)' : 'rotateZ(-15deg)'} + scale(${1 + Math.sin(Date.now() / 1000) * 0.1}) + `, + transition: isDying ? 'opacity 1s ease-out' : 'none', + fontSize: '24px', + color, + opacity: isDying ? (Date.now() - dyingStartTime! > 500 ? 0 : 1) : 1, + } + + return
{isDying && Date.now() - dyingStartTime! > 500 ? '☠️' : '🐠'}
+} diff --git a/showcase/fishies/src/components/FishTank.tsx b/showcase/fishies/src/components/FishTank.tsx new file mode 100644 index 0000000..56e7a84 --- /dev/null +++ b/showcase/fishies/src/components/FishTank.tsx @@ -0,0 +1,267 @@ +import { useEffect, useState, useCallback } from 'react' +import { Fish } from './Fish' +import { Shark } from './Shark' +import { WhaleShark } from './WhaleShark' + +interface Position { + x: number + y: number +} + +interface FishState extends Position { + id: number + x: number + y: number + direction: number + color: string + speedX: number + speedY: number + isDying?: boolean + dyingStartTime?: number + isBeingEaten?: boolean +} + +interface PredatorState extends Position { + direction: number + speed: number +} + +const COLORS = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD'] +const SHARK_SPEED = 3 +const WHALE_SHARK_SPEED = 4 // Fast enough to catch the shark +const BASE_FISH_SPEED = 0.5 // Much slower base speed for fish +const MAX_FISH_SPEED_MULTIPLIER = 1.5 // More moderate speed increase when fleeing + +export const FishTank: React.FC = () => { + const [fishes, setFishes] = useState(() => + Array.from({ length: 10 }, (_, i) => ({ + id: i, + x: Math.random() * window.innerWidth * 0.8, + y: Math.random() * window.innerHeight * 0.8, + direction: Math.random() < 0.5 ? -1 : 1, + color: COLORS[Math.floor(Math.random() * COLORS.length)], + speedX: (Math.random() * BASE_FISH_SPEED + BASE_FISH_SPEED) * (Math.random() < 0.5 ? -1 : 1), + speedY: (Math.random() - 0.5) * BASE_FISH_SPEED, + })) + ) + + const [shark, setShark] = useState(() => ({ + x: window.innerWidth / 2, + y: window.innerHeight / 2, + direction: 1, + speed: SHARK_SPEED, + })) + + const [whaleShark, setWhaleShark] = useState(() => ({ + x: window.innerWidth * 0.8, + y: window.innerHeight * 0.8, + direction: -1, + speed: WHALE_SHARK_SPEED, + })) + + // Find nearest fish to shark + const findNearestFish = useCallback((shark: Position, fishes: Position[]): Position | null => { + if (fishes.length === 0) return null + + return fishes.reduce((nearest, current) => { + const distToCurrent = Math.hypot(current.x - shark.x, current.y - shark.y) + const distToNearest = Math.hypot(nearest.x - shark.x, nearest.y - shark.y) + return distToCurrent < distToNearest ? current : nearest + }) + }, []) + + // Move predator towards target + const moveTowards = (predator: PredatorState, target: Position): PredatorState => { + const dx = target.x - predator.x + const dy = target.y - predator.y + const distance = Math.hypot(dx, dy) + + if (distance < 1) return predator + + return { + x: predator.x + (dx / distance) * predator.speed, + y: predator.y + (dy / distance) * predator.speed, + direction: dx > 0 ? 1 : -1, + speed: predator.speed, + } + } + + // Make whale shark protect nearby fish by pushing shark away + const protectFish = useCallback((whaleShark: Position, shark: PredatorState, fishes: FishState[]): PredatorState => { + // Find closest fish to shark + const nearestFish = findNearestFish(shark, fishes) + if (!nearestFish) return shark + + const sharkToFish = Math.hypot(nearestFish.x - shark.x, nearestFish.y - shark.y) + const whaleToShark = Math.hypot(whaleShark.x - shark.x, whaleShark.y - shark.y) + + // If shark is close to a fish and whale is close enough to intervene + if (sharkToFish < 150 && whaleToShark < 100) { + // Slap the shark away with more force + const angle = Math.atan2(shark.y - whaleShark.y, shark.x - whaleShark.x) + const slappedShark = { + ...shark, + x: shark.x + Math.cos(angle) * 250, // Longer distance + y: shark.y + Math.sin(angle) * 250, + direction: Math.cos(angle) > 0 ? 1 : -1, + } + return slappedShark + } + return shark + }, [findNearestFish]) + + useEffect(() => { + const interval = setInterval(() => { + setFishes(prevFishes => prevFishes.map(fish => { + // Return dying fish without any movement updates + if (fish.isDying) { + return fish + } + + let newX = fish.x + fish.speedX + let newY = fish.y + fish.speedY + let newDirection = fish.direction + + // Keep fish within bounds + const newXConstrained = Math.max(0, Math.min(newX, window.innerWidth - 40)) + const newYConstrained = Math.max(0, Math.min(newY, window.innerHeight - 40)) + + // Change direction if hitting walls + if (newXConstrained !== newX) { + newDirection *= -1 + } + + // Update position to constrained values + newX = newXConstrained + newY = newYConstrained + + // More gentle speed adjustment based on distance to shark + const distToShark = Math.hypot(shark.x - newX, shark.y - newY) + let speedMultiplier = 1 + if (distToShark < 200) { + // Smooth easing function for speed increase + const normalizedDist = distToShark / 200 + const easeOutQuad = 1 - normalizedDist * normalizedDist + speedMultiplier = 1 + (MAX_FISH_SPEED_MULTIPLIER - 1) * easeOutQuad + } + + // Apply speed multiplier to base speeds, not current speeds + const adjustedSpeedX = (fish.speedX / Math.abs(fish.speedX)) * BASE_FISH_SPEED * speedMultiplier + const adjustedSpeedY = (fish.speedY / Math.abs(fish.speedY || 1)) * BASE_FISH_SPEED * 0.5 * speedMultiplier + + return { + ...fish, + x: newX, + y: newY, + direction: newDirection, + speedX: adjustedSpeedX, + speedY: adjustedSpeedY, + } + })) + + // Update shark position with bounds checking + setShark(prevShark => { + const nearestFish = findNearestFish(prevShark, fishes) + let newShark = prevShark + if (nearestFish) { + newShark = moveTowards(prevShark, nearestFish) + } + newShark = protectFish(whaleShark, newShark, fishes) + + // Keep shark within bounds + return { + ...newShark, + x: Math.max(0, Math.min(newShark.x, window.innerWidth - 60)), + y: Math.max(0, Math.min(newShark.y, window.innerHeight - 60)), + } + }) + + // Update whale shark position with bounds checking + setWhaleShark(prevWhaleShark => { + const nearestFish = findNearestFish(shark, fishes) + let newWhaleShark = prevWhaleShark + + if (nearestFish && Math.hypot(nearestFish.x - shark.x, nearestFish.y - shark.y) < 150) { + newWhaleShark = moveTowards(prevWhaleShark, shark) + } else { + // Patrol pattern + newWhaleShark = { + ...prevWhaleShark, + x: prevWhaleShark.x + Math.cos(Date.now() / 2000) * 2, + y: prevWhaleShark.y + Math.sin(Date.now() / 1500) * 2, + direction: Math.cos(Date.now() / 2000) > 0 ? 1 : -1, + } + } + + // Keep whale shark within bounds + return { + ...newWhaleShark, + x: Math.max(0, Math.min(newWhaleShark.x, window.innerWidth - 80)), + y: Math.max(0, Math.min(newWhaleShark.y, window.innerHeight - 80)), + } + }) + + // Check for collisions and update fish + setFishes(prevFishes => { + // First check collisions + const updatedFishes = prevFishes.map(fish => { + if (fish.isDying) return fish + + // Check if shark is close enough and moving towards the fish + const dx = fish.x - shark.x + const dy = fish.y - shark.y + const distance = Math.hypot(dx, dy) + + if (distance < 30) { // Close attack range + const sharkMovingTowardsFish = ( + (dx > 0 && shark.direction > 0) || // Fish is to right and shark facing right + (dx < 0 && shark.direction < 0) // Fish is to left and shark facing left + ) + + if (sharkMovingTowardsFish) { + return { ...fish, isBeingEaten: true } + } + } else if (fish.isBeingEaten) { // Shark just moved away after attack + return { ...fish, isBeingEaten: false, isDying: true, dyingStartTime: Date.now() } + } + return fish + }) + + // Then remove fish that have completed their death animation + return updatedFishes.filter(fish => { + if (!fish.isDying) return true + const timeSinceDeath = Date.now() - fish.dyingStartTime! + return timeSinceDeath < 1000 + }) + }) + }, 50) + + return () => clearInterval(interval) + }, [fishes, shark, whaleShark, protectFish, findNearestFish]) + + return ( +
+ {fishes.map(fish => ( + + ))} + + +
+ ) +} diff --git a/showcase/fishies/src/components/Shark.tsx b/showcase/fishies/src/components/Shark.tsx new file mode 100644 index 0000000..abead56 --- /dev/null +++ b/showcase/fishies/src/components/Shark.tsx @@ -0,0 +1,24 @@ +import { CSSProperties } from 'react' + +interface SharkProps { + x: number + y: number + direction: number +} + +export const Shark: React.FC = ({ x, y, direction }) => { + const style: CSSProperties = { + position: 'absolute', + left: `${x}px`, + top: `${y}px`, + transform: ` + translate3d(0, 0, ${Math.sin(Date.now() / 1200) * 300}px) + rotateY(${direction > 0 ? 0 : 180}deg) + scale(${1 + Math.sin(Date.now() / 1200) * 0.15}) + `, + transition: 'all 0.3s ease-in-out', + fontSize: '40px', // Bigger than fish + } + + return
🦈
+} diff --git a/showcase/fishies/src/components/WhaleShark.tsx b/showcase/fishies/src/components/WhaleShark.tsx new file mode 100644 index 0000000..7ac6cc5 --- /dev/null +++ b/showcase/fishies/src/components/WhaleShark.tsx @@ -0,0 +1,24 @@ +import { CSSProperties } from 'react' + +interface WhaleSharkProps { + x: number + y: number + direction: number +} + +export const WhaleShark: React.FC = ({ x, y, direction }) => { + const style: CSSProperties = { + position: 'absolute', + left: `${x}px`, + top: `${y}px`, + transform: ` + translate3d(0, 0, ${Math.sin(Date.now() / 1500) * 400}px) + rotateY(${direction > 0 ? 0 : 180}deg) + scale(${1 + Math.sin(Date.now() / 1500) * 0.2}) + `, + transition: 'all 0.3s ease-in-out', + fontSize: '64px', // Much bigger than shark + } + + return
🐋
+} diff --git a/showcase/fishies/src/index.css b/showcase/fishies/src/index.css new file mode 100644 index 0000000..b543b88 --- /dev/null +++ b/showcase/fishies/src/index.css @@ -0,0 +1,32 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + margin: 0; + display: flex; + min-width: 320px; + min-height: 100vh; +} + +#root { + width: 100%; + height: 100vh; +} diff --git a/showcase/fishies/src/main.tsx b/showcase/fishies/src/main.tsx new file mode 100644 index 0000000..bef5202 --- /dev/null +++ b/showcase/fishies/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/showcase/fishies/src/vite-env.d.ts b/showcase/fishies/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/showcase/fishies/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/showcase/fishies/tsconfig.app.json b/showcase/fishies/tsconfig.app.json new file mode 100644 index 0000000..76dfc1b --- /dev/null +++ b/showcase/fishies/tsconfig.app.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "incremental": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + }, + "include": ["src"] +} diff --git a/showcase/fishies/tsconfig.json b/showcase/fishies/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/showcase/fishies/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/showcase/fishies/tsconfig.node.json b/showcase/fishies/tsconfig.node.json new file mode 100644 index 0000000..88a892c --- /dev/null +++ b/showcase/fishies/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + "incremental": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + }, + "include": ["vite.config.ts"] +} diff --git a/showcase/fishies/vite.config.ts b/showcase/fishies/vite.config.ts new file mode 100644 index 0000000..8b0f57b --- /dev/null +++ b/showcase/fishies/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +}) From c0baece46adb95c18d13d2e8adad6fcd48d612af Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 30 Jan 2025 15:29:58 -0800 Subject: [PATCH 11/34] Update convex knowledge based on official guide --- starter-templates/convex/convex.knowledge.md | 610 ++++++++++++++----- 1 file changed, 466 insertions(+), 144 deletions(-) diff --git a/starter-templates/convex/convex.knowledge.md b/starter-templates/convex/convex.knowledge.md index 4c738e4..676b49e 100644 --- a/starter-templates/convex/convex.knowledge.md +++ b/starter-templates/convex/convex.knowledge.md @@ -1,174 +1,496 @@ +--- +description: Guidelines and best practices for building Convex projects, including database schema design, queries, mutations, and real-world examples +globs: **/*.{ts,tsx,js,jsx} +--- -The following text has been compressed by you (the LLM) to save space. Decode the text to reconstruct and understand the original context. The decoded text contains compressed information about Convex, React, and web development practices: +Downloaded from: https://docs.convex.dev/ai -# Convex Development Guide + + + + - ALWAYS use the new function syntax for Convex functions. For example: + ```typescript + import { query } from "./_generated/server"; + import { v } from "convex/values"; + export const f = query({ + args: {}, + returns: v.null(), + handler: async (ctx, args) => { + // Function body + }, + }); + ``` + + + - HTTP endpoints are defined in `convex/http.ts` and require an `httpAction` decorator. For example: + ```typescript + import { httpRouter } from "convex/server"; + import { httpAction } from "./_generated/server"; + const http = httpRouter(); + http.route({ + path: "/echo", + method: "POST", + handler: httpAction(async (ctx, req) => { + const body = await req.bytes(); + return new Response(body, { status: 200 }); + }), + }); + ``` + - HTTP endpoints are always registered at the exact path you specify in the `path` field. For example, if you specify `/api/someRoute`, the endpoint will be registered at `/api/someRoute`. + + + - Use `internalQuery`, `internalMutation`, and `internalAction` to register internal functions. These functions are private and aren't part of an app's API. They can only be called by other Convex functions. + - Use `query`, `mutation`, and `action` to register public functions. These functions are part of the public API and are exposed to the public Internet. Do NOT use `query`, `mutation`, or `action` to register sensitive internal functions that should be kept private. + - You CANNOT register a function through the `api` or `internal` objects. + - ALWAYS include argument and return validators for all Convex functions. If a function doesn't return anything, include `returns: v.null()` as its output validator. + - If the JavaScript implementation of a Convex function doesn't have a return value, it implicitly returns `null`. + + + - Use `ctx.runQuery` to call a query from a query, mutation, or action. + - Use `ctx.runMutation` to call a mutation from a mutation or action. + - Use `ctx.runAction` to call an action from an action. + - ONLY call an action from another action if you need to cross runtimes (e.g. from V8 to Node). Otherwise, pull out the shared code into a helper async function and call that directly instead. + - Try to use as few calls from actions to queries and mutations as possible. Queries and mutations are transactions, so splitting logic up into multiple calls introduces the risk of race conditions. + - All of these calls take in a `FunctionReference`. Do NOT try to pass the callee function directly into one of these calls. + - When using `ctx.runQuery`, `ctx.runMutation`, or `ctx.runAction` to call a function in the same file, specify a type annotation on the return value to work around TypeScript circularity limitations. For example, + ``` + export const f = query({ + args: { name: v.string() }, + returns: v.string(), + handler: async (ctx, args) => { + return "Hello " + args.name; + }, + }); -## Convex Specifics + export const g = query({ + args: {}, + returns: v.null(), + handler: async (ctx, args) => { + const result: string = await ctx.runQuery(api.example.f, { name: "Bob" }); + return null; + }, + }); + ``` + + + - Function references are pointers to registered Convex functions. + - Use the `api` object defined by the framework in `convex/_generated/api.ts` to call public functions registered with `query`, `mutation`, or `action`. + - Use the `internal` object defined by the framework in `convex/_generated/api.ts` to call internal (or private) functions registered with `internalQuery`, `internalMutation`, or `internalAction`. + - Convex uses file-based routing, so a public function defined in `convex/example.ts` named `f` has a function reference of `api.example.f`. + - A private function defined in `convex/example.ts` named `g` has a function reference of `internal.example.g`. + - Functions can also registered within directories nested within the `convex/` folder. For example, a public function `h` defined in `convex/messages/access.ts` has a function reference of `api.messages.access.h`. + + + - Convex uses file-based routing, so thoughtfully organize files with public query, mutation, or action functions within the `convex/` directory. + - Use `query`, `mutation`, and `action` to define public functions. + - Use `internalQuery`, `internalMutation`, and `internalAction` to define private, internal functions. + + + + - `v.bigint()` is deprecated for representing signed 64-bit integers. Use `v.int64()` instead. + - Use `v.record()` for defining a record type. `v.map()` and `v.set()` are not supported. + + + - Always define your schema in `convex/schema.ts`. + - Always import the schema definition functions from `convex/server`: + - System fields are automatically added to all documents and are prefixed with an underscore. + + + - You can use the helper typescript type `Id` imported from './_generated/dataModel' to get the type of the id for a given table. For example if there is a table called 'users' you can use `Id<'users'>` to get the type of the id for that table. + - If you need to define a `Record` make sure that you correctly provide the type of the key and value in the type. For example a validator `v.record(v.id('users'), v.string())` would have the type `Record, string>`. + - Be strict with types, particularly around id's of documents. For example, if a function takes in an id for a document in the 'users' table, take in `Id<'users'>` rather than `string`. + + + - A query for "10 messages in channel '#general' that best match the query 'hello hi' in their body" would look like: -### Query -// -import { query } from "./_generated/server"; -import { v } from "convex/values"; +const messages = await ctx.db + .query("messages") + .withSearchIndex("search_body", (q) => + q.search("body", "hello hi").eq("channel", "#general"), + ) + .take(10); + + + - Do NOT use `filter` in queries. Instead, define an index in the schema and use `withIndex` instead. + - Convex queries do NOT support `.delete()`. Instead, `.collect()` the results, iterate over them, and call `ctx.db.delete(row._id)` on each result. + - Use `.unique()` to get a single document from a query. This method will throw an error if there are multiple documents that match the query. + + - By default Convex always returns documents in ascending `_creationTime` order. + - You can use `.order('asc')` or `.order('desc')` to pick whether a query is in ascending or descending order. If the order isn't specified, it defaults to ascending. + - Document queries that use indexes will be ordered based on the columns in the index and can avoid slow table scans. + + + + - Use `ctx.db.replace` to fully replace an existing document. This method will throw an error if the document does not exist. + - Use `ctx.db.patch` to shallow merge updates into an existing document. This method will throw an error if the document does not exist. + + + + - Only use the `crons.interval` or `crons.cron` methods to schedule cron jobs. Do NOT use the `crons.hourly`, `crons.daily`, or `crons.weekly` helpers. + - Both cron methods take in a FunctionReference. Do NOT try to pass the function directly into one of these methods. + - Define crons by declaring the top-level `crons` object, calling some methods on it, and then exporting it as default. For example, + ```ts + import { cronJobs } from "convex/server"; + import { internal } from "./_generated/api"; -export const getTaskList = query({ - args: { taskListId: v.id("taskLists") }, - handler: async (ctx, args) => { - const tasks = await ctx.db - .query("tasks") - .filter((q) => q.eq(q.field("taskListId"), args.taskListId)) - .order("desc") - .take(100); - return tasks; - } -}); -// - -Name: path+file+export=api.path.name -Nest: convex/foo/file.ts=api.foo.file.fn -Def: export default=api.file.default -Non-JS: string "path/file:fn" -Constr: query({handler:()=>{}}) -Args: 2nd param, named, serialize -Ctx: 1st param, db, storage, auth -Helper: async function helper(ctx:QueryCtx, arg){} -NPM: import{faker}from"@faker-js/faker" - -**IMPORTANT: Prefer to use Convex indexes over filters**. Here's an example: - -// -// schema.ts -import { defineSchema, defineTable } from "convex/server"; -import { v } from "convex/values"; + const crons = cronJobs(); -// Define a messages table with two indexes. -export default defineSchema({ - messages: defineTable({ - channel: v.id("channels"), - body: v.string(), - user: v.id("users"), - }) - .index("by_channel", ["channel"]) - .index("by_channel_user", ["channel", "user"]), -}); -// + // Run `internal.users.deleteInactive` every two hours. + crons.interval("delete inactive users", { hours: 2 }, internal.users.deleteInactive, {}); -And use an index like this (note the syntax is different than filter): + export default crons; + ``` + - You can register Convex functions within `crons.ts` just like any other file. + - If a cron calls an internal function, always import the `internal` object from '_generated/api`, even if the internal function is registered in the same file. + + + + - Convex includes file storage for large files like images, videos, and PDFs. + - The `ctx.storage.getUrl()` method returns a signed URL for a given file. It returns `null` if the file doesn't exist. + - Do NOT use the deprecated `ctx.storage.getMetadata` call for loading a file's metadata. -// -const messages = await ctx.db - .query("messages") - .withIndex("by_channel", (q) => - q - .eq("channel", channel) - .gt("_creationTime", Date.now() - 2 * 60000) - .lt("_creationTime", Date.now() - 60000), - ) - .collect(); -// + Instead, query the `_storage` system table. For example, you can use `ctx.db.system.get` to get an `Id<"_storage">`. + ``` + import { query } from "./_generated/server"; + import { Id } from "./_generated/dataModel"; + + type FileMetadata = { + _id: Id<"_storage">; + _creationTime: number; + contentType?: string; + sha256: string; + size: number; + } + export const exampleQuery = query({ + args: { fileId: v.id("_storage") }, + returns: v.null(); + handler: async (ctx, args) => { + const metadata: FileMetadata | null = await ctx.db.system.get(args.fileId); + console.log(metadata); + return null; + }, + }); + ``` + + -### Mutation -// -import { mutation } from "./_generated/server"; + + + + + Create a real-time chat application backend with AI responses. The app should: +- Allow creating users with names +- Support multiple chat channels +- Enable users to send messages to channels +- Automatically generate AI responses to user messages +- Show recent message history + +The backend should provide APIs for: +1. User management (creation) +2. Channel management (creation) +3. Message operations (sending, listing) +4. AI response generation using OpenAI's GPT-4 + +Messages should be stored with their channel, author, and content. The system should maintain message order +and limit history display to the 10 most recent messages per channel. + + + + + 1. Task Requirements Summary: +- Build a real-time chat backend with AI integration +- Support user creation +- Enable channel-based conversations +- Store and retrieve messages with proper ordering +- Generate AI responses automatically + +2. Main Components Needed: +- Database tables: users, channels, messages +- Public APIs for user/channel management +- Message handling functions +- Internal AI response generation system +- Context loading for AI responses + +3. Public API and Internal Functions Design: +Public Mutations: +- createUser: + - file path: convex/index.ts + - arguments: {name: v.string()} + - returns: v.object({userId: v.id("users")}) + - purpose: Create a new user with a given name +- createChannel: + - file path: convex/index.ts + - arguments: {name: v.string()} + - returns: v.object({channelId: v.id("channels")}) + - purpose: Create a new channel with a given name +- sendMessage: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels"), authorId: v.id("users"), content: v.string()} + - returns: v.null() + - purpose: Send a message to a channel and schedule a response from the AI + +Public Queries: +- listMessages: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels")} + - returns: v.array(v.object({ + _id: v.id("messages"), + _creationTime: v.number(), + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + })) + - purpose: List the 10 most recent messages from a channel in descending creation order + +Internal Functions: +- generateResponse: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels")} + - returns: v.null() + - purpose: Generate a response from the AI for a given channel +- loadContext: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels")} + - returns: v.array(v.object({ + _id: v.id("messages"), + _creationTime: v.number(), + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + })) +- writeAgentResponse: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels"), content: v.string()} + - returns: v.null() + - purpose: Write an AI response to a given channel + +4. Schema Design: +- users + - validator: { name: v.string() } + - indexes: +- channels + - validator: { name: v.string() } + - indexes: +- messages + - validator: { channelId: v.id("channels"), authorId: v.optional(v.id("users")), content: v.string() } + - indexes + - by_channel: ["channelId"] + +5. Background Processing: +- AI response generation runs asynchronously after each user message +- Uses OpenAI's GPT-4 to generate contextual responses +- Maintains conversation context using recent message history + + + + { + "name": "chat-app", + "description": "This example shows how to build a chat app without authentication.", + "version": "1.0.0", + "dependencies": { + "convex": "^1.17.4", + "openai": "^4.79.0" + } +} + + + import { + query, + mutation, + internalQuery, + internalMutation, + internalAction, +} from "./_generated/server"; import { v } from "convex/values"; +import OpenAI from "openai"; +import { internal } from "./_generated/api"; -export const createTask = mutation({ - args: { text: v.string() }, +/** + * Create a user with a given name. + */ +export const createUser = mutation({ + args: { + name: v.string(), + }, + returns: v.id("users"), handler: async (ctx, args) => { - const newTaskId = await ctx.db.insert("tasks", { text: args.text }); - return newTaskId; - } + return await ctx.db.insert("users", { name: args.name }); + }, }); -// -### Action -// -import { action } from "./_generated/server"; -import { internal } from "./_generated/api"; -import { v } from "convex/values"; +/** + * Create a channel with a given name. + */ +export const createChannel = mutation({ + args: { + name: v.string(), + }, + returns: v.id("channels"), + handler: async (ctx, args) => { + return await ctx.db.insert("channels", { name: args.name }); + }, +}); + +/** + * List the 10 most recent messages from a channel in descending creation order. + */ +export const listMessages = query({ + args: { + channelId: v.id("channels"), + }, + returns: v.array( + v.object({ + _id: v.id("messages"), + _creationTime: v.number(), + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + }), + ), + handler: async (ctx, args) => { + const messages = await ctx.db + .query("messages") + .withIndex("by_channel", (q) => q.eq("channelId", args.channelId)) + .order("desc") + .take(10); + return messages; + }, +}); -export const sendGif = action({ - args: { queryString: v.string(), author: v.string() }, - handler: async (ctx, { queryString, author }) => { - const data = await fetch(giphyUrl(queryString)); - const json = await data.json(); - if (!data.ok) { - throw new Error("Giphy error: " + JSON.stringify(json)); +/** + * Send a message to a channel and schedule a response from the AI. + */ +export const sendMessage = mutation({ + args: { + channelId: v.id("channels"), + authorId: v.id("users"), + content: v.string(), + }, + returns: v.null(), + handler: async (ctx, args) => { + const channel = await ctx.db.get(args.channelId); + if (!channel) { + throw new Error("Channel not found"); + } + const user = await ctx.db.get(args.authorId); + if (!user) { + throw new Error("User not found"); } - const gifEmbedUrl = json.data.embed_url; - await ctx.runMutation(internal.messages.sendGifMessage, { - body: gifEmbedUrl, - author + await ctx.db.insert("messages", { + channelId: args.channelId, + authorId: args.authorId, + content: args.content, }); - } + await ctx.scheduler.runAfter(0, internal.index.generateResponse, { + channelId: args.channelId, + }); + return null; + }, }); -// -### HTTP Router -// -import { httpRouter } from "convex/server"; +const openai = new OpenAI(); -const http = httpRouter(); -http.route({ - path: "/postMessage", - method: "POST", - handler: postMessage, -}); -http.route({ - pathPrefix: "/getAuthorMessages/", - method: "GET", - handler: getByAuthorPathSuffix, +export const generateResponse = internalAction({ + args: { + channelId: v.id("channels"), + }, + returns: v.null(), + handler: async (ctx, args) => { + const context = await ctx.runQuery(internal.index.loadContext, { + channelId: args.channelId, + }); + const response = await openai.chat.completions.create({ + model: "gpt-4o", + messages: context, + }); + const content = response.choices[0].message.content; + if (!content) { + throw new Error("No content in response"); + } + await ctx.runMutation(internal.index.writeAgentResponse, { + channelId: args.channelId, + content, + }); + return null; + }, }); -export default http; -// -### Scheduled Jobs -// -import { cronJobs } from "convex/server"; -import { internal } from "./_generated/api"; +export const loadContext = internalQuery({ + args: { + channelId: v.id("channels"), + }, + returns: v.array( + v.object({ + role: v.union(v.literal("user"), v.literal("assistant")), + content: v.string(), + }), + ), + handler: async (ctx, args) => { + const channel = await ctx.db.get(args.channelId); + if (!channel) { + throw new Error("Channel not found"); + } + const messages = await ctx.db + .query("messages") + .withIndex("by_channel", (q) => q.eq("channelId", args.channelId)) + .order("desc") + .take(10); -const crons = cronJobs(); -crons.interval( - "clear messages table", - { minutes: 1 }, - internal.messages.clearAll, -); -crons.monthly( - "payment reminder", - { day: 1, hourUTC: 16, minuteUTC: 0 }, - internal.payments.sendPaymentEmail, - { email: "my_email@gmail.com" }, -); -export default crons; -// - -### File Handling -Upload: 3 steps (genURL, POST, saveID) - -Generate Upload URL: -// -import { mutation } from "./_generated/server"; - -export const generateUploadUrl = mutation(async (ctx) => { - return await ctx.storage.generateUploadUrl(); + const result = []; + for (const message of messages) { + if (message.authorId) { + const user = await ctx.db.get(message.authorId); + if (!user) { + throw new Error("User not found"); + } + result.push({ + role: "user" as const, + content: `${user.name}: ${message.content}`, + }); + } else { + result.push({ role: "assistant" as const, content: message.content }); + } + } + return result; + }, }); -// - -Save File ID: -// -import { mutation } from "./_generated/server"; -import { v } from "convex/values"; -export const sendImage = mutation({ - args: { storageId: v.id("_storage"), author: v.string() }, +export const writeAgentResponse = internalMutation({ + args: { + channelId: v.id("channels"), + content: v.string(), + }, + returns: v.null(), handler: async (ctx, args) => { await ctx.db.insert("messages", { - body: args.storageId, - author: args.author, - format: "image", + channelId: args.channelId, + content: args.content, }); - } + return null; + }, +}); + + + import { defineSchema, defineTable } from "convex/server"; +import { v } from "convex/values"; + +export default defineSchema({ + channels: defineTable({ + name: v.string(), + }), + + users: defineTable({ + name: v.string(), + }), + + messages: defineTable({ + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + }).index("by_channel", ["channelId"]), }); -// - -Follow Convex docs for Data Fetching, File Storage, Vector Databases, and Auth. + + + + From cf4673f48c6a4b49197d48c96356c460ca248ead Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 30 Jan 2025 15:33:00 -0800 Subject: [PATCH 12/34] Add top level .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store From 0bac8aa669608e37a076356b4b2eaa5ffc036d30 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 30 Jan 2025 15:47:08 -0800 Subject: [PATCH 13/34] Move convex knowledge into /knowledge --- {starter-templates/convex => knowledge}/convex.knowledge.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {starter-templates/convex => knowledge}/convex.knowledge.md (100%) diff --git a/starter-templates/convex/convex.knowledge.md b/knowledge/convex.knowledge.md similarity index 100% rename from starter-templates/convex/convex.knowledge.md rename to knowledge/convex.knowledge.md From 8c9d5a71b49aa1bcff81a3b996c3107873483990 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 30 Jan 2025 15:56:18 -0800 Subject: [PATCH 14/34] Add convex knowledge as a link to knowledge file --- starter-templates/convex/knowledge.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/starter-templates/convex/knowledge.md b/starter-templates/convex/knowledge.md index ee18642..13c3967 100644 --- a/starter-templates/convex/knowledge.md +++ b/starter-templates/convex/knowledge.md @@ -4,6 +4,10 @@ Generated by [Codebuff](https://www.npmjs.com/package/codebuff) Add any information here or instructions that will help Codebuff maintain your project. +## Convex knowledge + +https://raw.githubusercontent.com/CodebuffAI/codebuff-community/refs/heads/main/knowledge/convex.knowledge.md + ## Verifying changes After every change, run `npm run typecheck` to check for any errors that should be fixed. \ No newline at end of file From 5c0c1b627cfff3db61921b10177cc83b3f8d5b59 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 30 Jan 2025 15:59:33 -0800 Subject: [PATCH 15/34] Put back convex knowledge as separate file. --- starter-templates/convex/convex.knowledge.md | 496 +++++++++++++++++++ starter-templates/convex/knowledge.md | 4 - 2 files changed, 496 insertions(+), 4 deletions(-) create mode 100644 starter-templates/convex/convex.knowledge.md diff --git a/starter-templates/convex/convex.knowledge.md b/starter-templates/convex/convex.knowledge.md new file mode 100644 index 0000000..676b49e --- /dev/null +++ b/starter-templates/convex/convex.knowledge.md @@ -0,0 +1,496 @@ +--- +description: Guidelines and best practices for building Convex projects, including database schema design, queries, mutations, and real-world examples +globs: **/*.{ts,tsx,js,jsx} +--- + +Downloaded from: https://docs.convex.dev/ai + + + + + - ALWAYS use the new function syntax for Convex functions. For example: + ```typescript + import { query } from "./_generated/server"; + import { v } from "convex/values"; + export const f = query({ + args: {}, + returns: v.null(), + handler: async (ctx, args) => { + // Function body + }, + }); + ``` + + + - HTTP endpoints are defined in `convex/http.ts` and require an `httpAction` decorator. For example: + ```typescript + import { httpRouter } from "convex/server"; + import { httpAction } from "./_generated/server"; + const http = httpRouter(); + http.route({ + path: "/echo", + method: "POST", + handler: httpAction(async (ctx, req) => { + const body = await req.bytes(); + return new Response(body, { status: 200 }); + }), + }); + ``` + - HTTP endpoints are always registered at the exact path you specify in the `path` field. For example, if you specify `/api/someRoute`, the endpoint will be registered at `/api/someRoute`. + + + - Use `internalQuery`, `internalMutation`, and `internalAction` to register internal functions. These functions are private and aren't part of an app's API. They can only be called by other Convex functions. + - Use `query`, `mutation`, and `action` to register public functions. These functions are part of the public API and are exposed to the public Internet. Do NOT use `query`, `mutation`, or `action` to register sensitive internal functions that should be kept private. + - You CANNOT register a function through the `api` or `internal` objects. + - ALWAYS include argument and return validators for all Convex functions. If a function doesn't return anything, include `returns: v.null()` as its output validator. + - If the JavaScript implementation of a Convex function doesn't have a return value, it implicitly returns `null`. + + + - Use `ctx.runQuery` to call a query from a query, mutation, or action. + - Use `ctx.runMutation` to call a mutation from a mutation or action. + - Use `ctx.runAction` to call an action from an action. + - ONLY call an action from another action if you need to cross runtimes (e.g. from V8 to Node). Otherwise, pull out the shared code into a helper async function and call that directly instead. + - Try to use as few calls from actions to queries and mutations as possible. Queries and mutations are transactions, so splitting logic up into multiple calls introduces the risk of race conditions. + - All of these calls take in a `FunctionReference`. Do NOT try to pass the callee function directly into one of these calls. + - When using `ctx.runQuery`, `ctx.runMutation`, or `ctx.runAction` to call a function in the same file, specify a type annotation on the return value to work around TypeScript circularity limitations. For example, + ``` + export const f = query({ + args: { name: v.string() }, + returns: v.string(), + handler: async (ctx, args) => { + return "Hello " + args.name; + }, + }); + + export const g = query({ + args: {}, + returns: v.null(), + handler: async (ctx, args) => { + const result: string = await ctx.runQuery(api.example.f, { name: "Bob" }); + return null; + }, + }); + ``` + + + - Function references are pointers to registered Convex functions. + - Use the `api` object defined by the framework in `convex/_generated/api.ts` to call public functions registered with `query`, `mutation`, or `action`. + - Use the `internal` object defined by the framework in `convex/_generated/api.ts` to call internal (or private) functions registered with `internalQuery`, `internalMutation`, or `internalAction`. + - Convex uses file-based routing, so a public function defined in `convex/example.ts` named `f` has a function reference of `api.example.f`. + - A private function defined in `convex/example.ts` named `g` has a function reference of `internal.example.g`. + - Functions can also registered within directories nested within the `convex/` folder. For example, a public function `h` defined in `convex/messages/access.ts` has a function reference of `api.messages.access.h`. + + + - Convex uses file-based routing, so thoughtfully organize files with public query, mutation, or action functions within the `convex/` directory. + - Use `query`, `mutation`, and `action` to define public functions. + - Use `internalQuery`, `internalMutation`, and `internalAction` to define private, internal functions. + + + + - `v.bigint()` is deprecated for representing signed 64-bit integers. Use `v.int64()` instead. + - Use `v.record()` for defining a record type. `v.map()` and `v.set()` are not supported. + + + - Always define your schema in `convex/schema.ts`. + - Always import the schema definition functions from `convex/server`: + - System fields are automatically added to all documents and are prefixed with an underscore. + + + - You can use the helper typescript type `Id` imported from './_generated/dataModel' to get the type of the id for a given table. For example if there is a table called 'users' you can use `Id<'users'>` to get the type of the id for that table. + - If you need to define a `Record` make sure that you correctly provide the type of the key and value in the type. For example a validator `v.record(v.id('users'), v.string())` would have the type `Record, string>`. + - Be strict with types, particularly around id's of documents. For example, if a function takes in an id for a document in the 'users' table, take in `Id<'users'>` rather than `string`. + + + - A query for "10 messages in channel '#general' that best match the query 'hello hi' in their body" would look like: + +const messages = await ctx.db + .query("messages") + .withSearchIndex("search_body", (q) => + q.search("body", "hello hi").eq("channel", "#general"), + ) + .take(10); + + + - Do NOT use `filter` in queries. Instead, define an index in the schema and use `withIndex` instead. + - Convex queries do NOT support `.delete()`. Instead, `.collect()` the results, iterate over them, and call `ctx.db.delete(row._id)` on each result. + - Use `.unique()` to get a single document from a query. This method will throw an error if there are multiple documents that match the query. + + - By default Convex always returns documents in ascending `_creationTime` order. + - You can use `.order('asc')` or `.order('desc')` to pick whether a query is in ascending or descending order. If the order isn't specified, it defaults to ascending. + - Document queries that use indexes will be ordered based on the columns in the index and can avoid slow table scans. + + + + - Use `ctx.db.replace` to fully replace an existing document. This method will throw an error if the document does not exist. + - Use `ctx.db.patch` to shallow merge updates into an existing document. This method will throw an error if the document does not exist. + + + + - Only use the `crons.interval` or `crons.cron` methods to schedule cron jobs. Do NOT use the `crons.hourly`, `crons.daily`, or `crons.weekly` helpers. + - Both cron methods take in a FunctionReference. Do NOT try to pass the function directly into one of these methods. + - Define crons by declaring the top-level `crons` object, calling some methods on it, and then exporting it as default. For example, + ```ts + import { cronJobs } from "convex/server"; + import { internal } from "./_generated/api"; + + const crons = cronJobs(); + + // Run `internal.users.deleteInactive` every two hours. + crons.interval("delete inactive users", { hours: 2 }, internal.users.deleteInactive, {}); + + export default crons; + ``` + - You can register Convex functions within `crons.ts` just like any other file. + - If a cron calls an internal function, always import the `internal` object from '_generated/api`, even if the internal function is registered in the same file. + + + + - Convex includes file storage for large files like images, videos, and PDFs. + - The `ctx.storage.getUrl()` method returns a signed URL for a given file. It returns `null` if the file doesn't exist. + - Do NOT use the deprecated `ctx.storage.getMetadata` call for loading a file's metadata. + + Instead, query the `_storage` system table. For example, you can use `ctx.db.system.get` to get an `Id<"_storage">`. + ``` + import { query } from "./_generated/server"; + import { Id } from "./_generated/dataModel"; + + type FileMetadata = { + _id: Id<"_storage">; + _creationTime: number; + contentType?: string; + sha256: string; + size: number; + } + + export const exampleQuery = query({ + args: { fileId: v.id("_storage") }, + returns: v.null(); + handler: async (ctx, args) => { + const metadata: FileMetadata | null = await ctx.db.system.get(args.fileId); + console.log(metadata); + return null; + }, + }); + ``` + + + + + + + + Create a real-time chat application backend with AI responses. The app should: +- Allow creating users with names +- Support multiple chat channels +- Enable users to send messages to channels +- Automatically generate AI responses to user messages +- Show recent message history + +The backend should provide APIs for: +1. User management (creation) +2. Channel management (creation) +3. Message operations (sending, listing) +4. AI response generation using OpenAI's GPT-4 + +Messages should be stored with their channel, author, and content. The system should maintain message order +and limit history display to the 10 most recent messages per channel. + + + + + 1. Task Requirements Summary: +- Build a real-time chat backend with AI integration +- Support user creation +- Enable channel-based conversations +- Store and retrieve messages with proper ordering +- Generate AI responses automatically + +2. Main Components Needed: +- Database tables: users, channels, messages +- Public APIs for user/channel management +- Message handling functions +- Internal AI response generation system +- Context loading for AI responses + +3. Public API and Internal Functions Design: +Public Mutations: +- createUser: + - file path: convex/index.ts + - arguments: {name: v.string()} + - returns: v.object({userId: v.id("users")}) + - purpose: Create a new user with a given name +- createChannel: + - file path: convex/index.ts + - arguments: {name: v.string()} + - returns: v.object({channelId: v.id("channels")}) + - purpose: Create a new channel with a given name +- sendMessage: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels"), authorId: v.id("users"), content: v.string()} + - returns: v.null() + - purpose: Send a message to a channel and schedule a response from the AI + +Public Queries: +- listMessages: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels")} + - returns: v.array(v.object({ + _id: v.id("messages"), + _creationTime: v.number(), + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + })) + - purpose: List the 10 most recent messages from a channel in descending creation order + +Internal Functions: +- generateResponse: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels")} + - returns: v.null() + - purpose: Generate a response from the AI for a given channel +- loadContext: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels")} + - returns: v.array(v.object({ + _id: v.id("messages"), + _creationTime: v.number(), + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + })) +- writeAgentResponse: + - file path: convex/index.ts + - arguments: {channelId: v.id("channels"), content: v.string()} + - returns: v.null() + - purpose: Write an AI response to a given channel + +4. Schema Design: +- users + - validator: { name: v.string() } + - indexes: +- channels + - validator: { name: v.string() } + - indexes: +- messages + - validator: { channelId: v.id("channels"), authorId: v.optional(v.id("users")), content: v.string() } + - indexes + - by_channel: ["channelId"] + +5. Background Processing: +- AI response generation runs asynchronously after each user message +- Uses OpenAI's GPT-4 to generate contextual responses +- Maintains conversation context using recent message history + + + + { + "name": "chat-app", + "description": "This example shows how to build a chat app without authentication.", + "version": "1.0.0", + "dependencies": { + "convex": "^1.17.4", + "openai": "^4.79.0" + } +} + + + import { + query, + mutation, + internalQuery, + internalMutation, + internalAction, +} from "./_generated/server"; +import { v } from "convex/values"; +import OpenAI from "openai"; +import { internal } from "./_generated/api"; + +/** + * Create a user with a given name. + */ +export const createUser = mutation({ + args: { + name: v.string(), + }, + returns: v.id("users"), + handler: async (ctx, args) => { + return await ctx.db.insert("users", { name: args.name }); + }, +}); + +/** + * Create a channel with a given name. + */ +export const createChannel = mutation({ + args: { + name: v.string(), + }, + returns: v.id("channels"), + handler: async (ctx, args) => { + return await ctx.db.insert("channels", { name: args.name }); + }, +}); + +/** + * List the 10 most recent messages from a channel in descending creation order. + */ +export const listMessages = query({ + args: { + channelId: v.id("channels"), + }, + returns: v.array( + v.object({ + _id: v.id("messages"), + _creationTime: v.number(), + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + }), + ), + handler: async (ctx, args) => { + const messages = await ctx.db + .query("messages") + .withIndex("by_channel", (q) => q.eq("channelId", args.channelId)) + .order("desc") + .take(10); + return messages; + }, +}); + +/** + * Send a message to a channel and schedule a response from the AI. + */ +export const sendMessage = mutation({ + args: { + channelId: v.id("channels"), + authorId: v.id("users"), + content: v.string(), + }, + returns: v.null(), + handler: async (ctx, args) => { + const channel = await ctx.db.get(args.channelId); + if (!channel) { + throw new Error("Channel not found"); + } + const user = await ctx.db.get(args.authorId); + if (!user) { + throw new Error("User not found"); + } + await ctx.db.insert("messages", { + channelId: args.channelId, + authorId: args.authorId, + content: args.content, + }); + await ctx.scheduler.runAfter(0, internal.index.generateResponse, { + channelId: args.channelId, + }); + return null; + }, +}); + +const openai = new OpenAI(); + +export const generateResponse = internalAction({ + args: { + channelId: v.id("channels"), + }, + returns: v.null(), + handler: async (ctx, args) => { + const context = await ctx.runQuery(internal.index.loadContext, { + channelId: args.channelId, + }); + const response = await openai.chat.completions.create({ + model: "gpt-4o", + messages: context, + }); + const content = response.choices[0].message.content; + if (!content) { + throw new Error("No content in response"); + } + await ctx.runMutation(internal.index.writeAgentResponse, { + channelId: args.channelId, + content, + }); + return null; + }, +}); + +export const loadContext = internalQuery({ + args: { + channelId: v.id("channels"), + }, + returns: v.array( + v.object({ + role: v.union(v.literal("user"), v.literal("assistant")), + content: v.string(), + }), + ), + handler: async (ctx, args) => { + const channel = await ctx.db.get(args.channelId); + if (!channel) { + throw new Error("Channel not found"); + } + const messages = await ctx.db + .query("messages") + .withIndex("by_channel", (q) => q.eq("channelId", args.channelId)) + .order("desc") + .take(10); + + const result = []; + for (const message of messages) { + if (message.authorId) { + const user = await ctx.db.get(message.authorId); + if (!user) { + throw new Error("User not found"); + } + result.push({ + role: "user" as const, + content: `${user.name}: ${message.content}`, + }); + } else { + result.push({ role: "assistant" as const, content: message.content }); + } + } + return result; + }, +}); + +export const writeAgentResponse = internalMutation({ + args: { + channelId: v.id("channels"), + content: v.string(), + }, + returns: v.null(), + handler: async (ctx, args) => { + await ctx.db.insert("messages", { + channelId: args.channelId, + content: args.content, + }); + return null; + }, +}); + + + import { defineSchema, defineTable } from "convex/server"; +import { v } from "convex/values"; + +export default defineSchema({ + channels: defineTable({ + name: v.string(), + }), + + users: defineTable({ + name: v.string(), + }), + + messages: defineTable({ + channelId: v.id("channels"), + authorId: v.optional(v.id("users")), + content: v.string(), + }).index("by_channel", ["channelId"]), +}); + + + + diff --git a/starter-templates/convex/knowledge.md b/starter-templates/convex/knowledge.md index 13c3967..ee18642 100644 --- a/starter-templates/convex/knowledge.md +++ b/starter-templates/convex/knowledge.md @@ -4,10 +4,6 @@ Generated by [Codebuff](https://www.npmjs.com/package/codebuff) Add any information here or instructions that will help Codebuff maintain your project. -## Convex knowledge - -https://raw.githubusercontent.com/CodebuffAI/codebuff-community/refs/heads/main/knowledge/convex.knowledge.md - ## Verifying changes After every change, run `npm run typecheck` to check for any errors that should be fixed. \ No newline at end of file From 14b54cb7e71e2c7d26ba6dc20c89cdc87aab3a77 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 30 Jan 2025 16:08:36 -0800 Subject: [PATCH 16/34] Move codebuff-docker under utils directory --- {codebuff-docker => utils/codebuff-docker}/Dockerfile | 0 {codebuff-docker => utils/codebuff-docker}/README.md | 0 {codebuff-docker => utils/codebuff-docker}/entrypoint.sh | 0 {codebuff-docker => utils/codebuff-docker}/knowledge.md | 0 {codebuff-docker => utils/codebuff-docker}/start-codebuff.sh | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {codebuff-docker => utils/codebuff-docker}/Dockerfile (100%) rename {codebuff-docker => utils/codebuff-docker}/README.md (100%) rename {codebuff-docker => utils/codebuff-docker}/entrypoint.sh (100%) rename {codebuff-docker => utils/codebuff-docker}/knowledge.md (100%) rename {codebuff-docker => utils/codebuff-docker}/start-codebuff.sh (100%) diff --git a/codebuff-docker/Dockerfile b/utils/codebuff-docker/Dockerfile similarity index 100% rename from codebuff-docker/Dockerfile rename to utils/codebuff-docker/Dockerfile diff --git a/codebuff-docker/README.md b/utils/codebuff-docker/README.md similarity index 100% rename from codebuff-docker/README.md rename to utils/codebuff-docker/README.md diff --git a/codebuff-docker/entrypoint.sh b/utils/codebuff-docker/entrypoint.sh similarity index 100% rename from codebuff-docker/entrypoint.sh rename to utils/codebuff-docker/entrypoint.sh diff --git a/codebuff-docker/knowledge.md b/utils/codebuff-docker/knowledge.md similarity index 100% rename from codebuff-docker/knowledge.md rename to utils/codebuff-docker/knowledge.md diff --git a/codebuff-docker/start-codebuff.sh b/utils/codebuff-docker/start-codebuff.sh similarity index 100% rename from codebuff-docker/start-codebuff.sh rename to utils/codebuff-docker/start-codebuff.sh From 0e2ff299c8e8d16c45c26b332e9aff4b0c848300 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 30 Jan 2025 18:23:34 -0800 Subject: [PATCH 17/34] Add react-optimization.knowledge.md --- knowledge/react-optimization.knowledge.md | 169 ++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 knowledge/react-optimization.knowledge.md diff --git a/knowledge/react-optimization.knowledge.md b/knowledge/react-optimization.knowledge.md new file mode 100644 index 0000000..723c5d8 --- /dev/null +++ b/knowledge/react-optimization.knowledge.md @@ -0,0 +1,169 @@ +# React Code Optimization Guidelines + +When analyzing and modifying React code, examine the following patterns and implement the corresponding optimizations: + + + +1. **Component-Level Rerendering:** When analyzing code, identify if components are rerendering unnecessarily. Look for and fix the following patterns: + +- **State Changes High in the Tree:** Search for state changes high in the component tree that cause children to rerender unnecessarily. For example, if you see this pattern: + +```jsx +function ParentComponent() { + const [count, setCount] = useState(0) + return ( +
+ + +
+ ) +} +``` + +Modify the code to isolate state updates through component splitting or lifting state. + +- **Lack of Memoization:** When child components rerender even though their props haven't changed, implement `React.memo`. For example, transform this: + +```jsx +const ChildComponent = ({ style }) => { + console.log("ChildComponent rendering") + return
Child
+} +``` + +Into this: + +```jsx +const ChildComponent = React.memo(({ style }) => { + console.log("ChildComponent rendering") + return
Child
+}) +``` + +2. **Prop Instability:** + +- **Inline Objects/Arrays:** Look for and fix object or array literals passed as props inline. For example, transform this problematic pattern: + +```jsx +function ParentComponent() { + const [count, setCount] = useState(0) + return ( +
+ + +
+ ) +} +``` + +Into either this: + +```jsx +const childStyle = { color: "blue" } + +function ParentComponent() { + const [count, setCount] = useState(0) + return ( +
+ + +
+ ) +} +``` + +Or using `useMemo`: + +```jsx +function ParentComponent() { + const [count, setCount] = useState(0) + const childStyle = useMemo(() => ({ color: "blue" }), []) + return ( +
+ + +
+ ) +} +``` + +- **Inline Functions:** Search for and fix functions defined inline within props. Transform this: + +```jsx + +``` + +Into this: + +```jsx +const handleButtonClick = useCallback(() => handleClick(), []) +// ... + +``` + +When dependencies are needed: + +```jsx +const handleButtonClick = useCallback(() => handleClick(id), [id]) +``` + +- **Inline Function, Stable Value:** When reviewing memoized functions, verify that the dependency array is correctly managed. + +3. **Context Usage:** When examining React Context usage, check if context changes cause widespread rerendering. If found, implement more granular contexts or alternative state management. For example, transform this problematic pattern: + +```jsx +const BigContext = React.createContext() + +function Provider({ children }) { + const [frequently, setFrequently] = useState(0) + const [rarely, setRarely] = useState(0) + + const value = { frequently, rarely, setFrequently, setRarely } + + return ( + + {children} + + ) +} +``` + +Into this optimized version: + +```jsx +const FrequentContext = React.createContext() +const RareContext = React.createContext() + +function Provider({ children }) { + const [frequently, setFrequently] = useState(0) + const [rarely, setRarely] = useState(0) + + const frequentValue = useMemo(() => ({ frequently, setFrequently }), [frequently]) + const rareValue = useMemo(() => ({ rarely, setRarely }), [rarely]) + + return ( + + + {children} + + + ) +} +``` + +
+ + + +When optimizing code, remember that React's rerendering process (running the component's function and performing the virtual DOM diff) is separate from actual DOM updates. While a rerender doesn't always mean a DOM update, unnecessary rerenders still consume computational resources and should be eliminated through the patterns above. + + + +When analyzing and modifying code, structure the changes as follows: + +- **Problem Identification:** Identify the specific performance issue in the code. +- **Code Modification:** Apply the appropriate optimization pattern from above. +- **Verification:** Explain how the modification prevents unnecessary rerenders. +- **Testing:** Verify the optimization through React DevTools and performance monitoring. + +Continue this process for each component or section of code being optimized. \ No newline at end of file From 700c29fea770e0833e59e6379783a8d0b9d4142b Mon Sep 17 00:00:00 2001 From: Brandon Chen Date: Fri, 31 Jan 2025 11:56:27 -0800 Subject: [PATCH 18/34] feat: moar fishies (o3-mini-high testing) --- showcase/fishies/src/App.css | 67 +++- showcase/fishies/src/components/Bubble.tsx | 30 ++ showcase/fishies/src/components/Coral.tsx | 20 + showcase/fishies/src/components/Fish.tsx | 53 ++- showcase/fishies/src/components/FishTank.tsx | 367 +++++++++--------- showcase/fishies/src/components/Jellyfish.tsx | 22 ++ showcase/fishies/src/components/Seashell.tsx | 20 + showcase/fishies/src/components/Seaweed.tsx | 21 + showcase/fishies/src/components/Shark.tsx | 22 +- .../src/components/UnderwaterDecorations.tsx | 86 ++++ .../fishies/src/components/WhaleShark.tsx | 22 +- 11 files changed, 506 insertions(+), 224 deletions(-) create mode 100644 showcase/fishies/src/components/Bubble.tsx create mode 100644 showcase/fishies/src/components/Coral.tsx create mode 100644 showcase/fishies/src/components/Jellyfish.tsx create mode 100644 showcase/fishies/src/components/Seashell.tsx create mode 100644 showcase/fishies/src/components/Seaweed.tsx create mode 100644 showcase/fishies/src/components/UnderwaterDecorations.tsx diff --git a/showcase/fishies/src/App.css b/showcase/fishies/src/App.css index 35542a2..4ca17cb 100644 --- a/showcase/fishies/src/App.css +++ b/showcase/fishies/src/App.css @@ -2,16 +2,12 @@ width: 100vw; height: 100vh; overflow: hidden; - background: linear-gradient(180deg, - #87CEEB 0%, - rgba(135, 206, 235, 0.8) 20%, - rgba(30, 144, 255, 0.9) 60%, - #1E90FF 100% - ); + background: linear-gradient(180deg, #0f4c81 0%, #1e90ff 50%, #0d3b66 100%); perspective: 2000px; transform-style: preserve-3d; } +/* The fish-tank container holds all moving parts */ .fish-tank { width: 100%; height: 100%; @@ -19,7 +15,62 @@ animation: tank-depth 20s infinite ease-in-out; } +/* Subtle light-ray overlay for extra depth */ +.fish-tank::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: radial-gradient( + ellipse at center, + rgba(255, 255, 255, 0.1), + transparent + ); + pointer-events: none; + z-index: -1; +} + @keyframes tank-depth { - 0%, 100% { transform: translate3d(0, 0, 0); } - 50% { transform: translate3d(50px, 30px, -200px); } + 0%, + 100% { + transform: translate3d(0, 0, 0); + } + 50% { + transform: translate3d(50px, 30px, -200px); + } +} + +@keyframes jellyfish-float { + 0% { + transform: translate(0, 0) rotate(0deg); + } + 50% { + transform: translate(10px, -20px) rotate(5deg); + } + 100% { + transform: translate(0, 0) rotate(0deg); + } +} + +@keyframes bubble-rise { + 0% { + transform: translateY(0) scale(1); + opacity: 1; + } + 100% { + transform: translateY(-100px) scale(0.5); + opacity: 0; + } +} + +@keyframes sway { + 0%, + 100% { + transform: rotate(0deg); + } + 50% { + transform: rotate(5deg); + } } diff --git a/showcase/fishies/src/components/Bubble.tsx b/showcase/fishies/src/components/Bubble.tsx new file mode 100644 index 0000000..4b03132 --- /dev/null +++ b/showcase/fishies/src/components/Bubble.tsx @@ -0,0 +1,30 @@ +// src/components/Bubble.tsx +import { CSSProperties } from "react"; + +interface BubbleProps { + x: number; + y: number; + size?: number; + duration?: number; +} + +export const Bubble: React.FC = ({ + x, + y, + size = 10, + duration = 4, +}) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + width: `${size}px`, + height: `${size}px`, + backgroundColor: "rgba(255, 255, 255, 0.7)", + borderRadius: "50%", + zIndex: 0, + animation: `bubble-rise ${duration}s linear infinite`, + }; + + return
; +}; diff --git a/showcase/fishies/src/components/Coral.tsx b/showcase/fishies/src/components/Coral.tsx new file mode 100644 index 0000000..afecb8d --- /dev/null +++ b/showcase/fishies/src/components/Coral.tsx @@ -0,0 +1,20 @@ +// src/components/Coral.tsx +import { CSSProperties } from "react"; + +interface CoralProps { + x: number; + y: number; + size?: number; +} + +export const Coral: React.FC = ({ x, y, size = 40 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 0, + }; + + return
🪸
; +}; diff --git a/showcase/fishies/src/components/Fish.tsx b/showcase/fishies/src/components/Fish.tsx index 51e5ced..8146645 100644 --- a/showcase/fishies/src/components/Fish.tsx +++ b/showcase/fishies/src/components/Fish.tsx @@ -1,31 +1,52 @@ -import { CSSProperties } from 'react' +// src/components/Fish.tsx +import { CSSProperties } from "react"; interface FishProps { - x: number - y: number - direction: number - color: string - isDying?: boolean - dyingStartTime?: number - isBeingEaten?: boolean + x: number; + y: number; + direction: number; + color: string; + isDying?: boolean; + dyingStartTime?: number; + isBeingEaten?: boolean; } -export const Fish: React.FC = ({ x, y, direction, color, isDying, dyingStartTime, isBeingEaten }) => { +export const Fish: React.FC = ({ + x, + y, + direction, + color, + isDying, + dyingStartTime, + isBeingEaten, +}) => { const style: CSSProperties = { - position: 'absolute', + position: "absolute", left: `${x}px`, top: `${y}px`, + // Ensure fish (and later, predators) are rendered above decorations + zIndex: 1, transform: ` translate3d(0, 0, ${Math.sin(Date.now() / 1000) * 200}px) rotateY(${direction > 0 ? 0 : 180}deg) - ${isDying ? 'rotateZ(180deg)' : isBeingEaten ? 'rotateZ(0deg)' : 'rotateZ(-15deg)'} + ${ + isDying + ? "rotateZ(180deg)" + : isBeingEaten + ? "rotateZ(0deg)" + : "rotateZ(-15deg)" + } scale(${1 + Math.sin(Date.now() / 1000) * 0.1}) `, - transition: isDying ? 'opacity 1s ease-out' : 'none', - fontSize: '24px', + transition: isDying ? "opacity 1s ease-out" : "none", + fontSize: "24px", color, opacity: isDying ? (Date.now() - dyingStartTime! > 500 ? 0 : 1) : 1, - } + }; - return
{isDying && Date.now() - dyingStartTime! > 500 ? '☠️' : '🐠'}
-} + return ( +
+ {isDying && Date.now() - dyingStartTime! > 500 ? "☠️" : "🐠"} +
+ ); +}; diff --git a/showcase/fishies/src/components/FishTank.tsx b/showcase/fishies/src/components/FishTank.tsx index 56e7a84..67394e5 100644 --- a/showcase/fishies/src/components/FishTank.tsx +++ b/showcase/fishies/src/components/FishTank.tsx @@ -1,247 +1,258 @@ -import { useEffect, useState, useCallback } from 'react' -import { Fish } from './Fish' -import { Shark } from './Shark' -import { WhaleShark } from './WhaleShark' +// src/components/FishTank.tsx +import { useEffect, useState, useCallback } from "react"; +import { Fish } from "./Fish"; +import { Shark } from "./Shark"; +import { WhaleShark } from "./WhaleShark"; +import { UnderwaterDecorations } from "./UnderwaterDecorations"; interface Position { - x: number - y: number + x: number; + y: number; } interface FishState extends Position { - id: number - x: number - y: number - direction: number - color: string - speedX: number - speedY: number - isDying?: boolean - dyingStartTime?: number - isBeingEaten?: boolean + id: number; + direction: number; + color: string; + speedX: number; + speedY: number; + isDying?: boolean; + dyingStartTime?: number; + isBeingEaten?: boolean; } interface PredatorState extends Position { - direction: number - speed: number + direction: number; + speed: number; } -const COLORS = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD'] -const SHARK_SPEED = 3 -const WHALE_SHARK_SPEED = 4 // Fast enough to catch the shark -const BASE_FISH_SPEED = 0.5 // Much slower base speed for fish -const MAX_FISH_SPEED_MULTIPLIER = 1.5 // More moderate speed increase when fleeing +const COLORS = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEEAD"]; +const SHARK_SPEED = 3; +const WHALE_SHARK_SPEED = 4; +const BASE_FISH_SPEED = 0.5; +const MAX_FISH_SPEED_MULTIPLIER = 1.5; export const FishTank: React.FC = () => { - const [fishes, setFishes] = useState(() => + const [fishes, setFishes] = useState(() => Array.from({ length: 10 }, (_, i) => ({ id: i, x: Math.random() * window.innerWidth * 0.8, y: Math.random() * window.innerHeight * 0.8, direction: Math.random() < 0.5 ? -1 : 1, color: COLORS[Math.floor(Math.random() * COLORS.length)], - speedX: (Math.random() * BASE_FISH_SPEED + BASE_FISH_SPEED) * (Math.random() < 0.5 ? -1 : 1), + speedX: + (Math.random() * BASE_FISH_SPEED + BASE_FISH_SPEED) * + (Math.random() < 0.5 ? -1 : 1), speedY: (Math.random() - 0.5) * BASE_FISH_SPEED, })) - ) + ); const [shark, setShark] = useState(() => ({ x: window.innerWidth / 2, y: window.innerHeight / 2, direction: 1, speed: SHARK_SPEED, - })) + })); const [whaleShark, setWhaleShark] = useState(() => ({ x: window.innerWidth * 0.8, y: window.innerHeight * 0.8, direction: -1, speed: WHALE_SHARK_SPEED, - })) + })); - // Find nearest fish to shark - const findNearestFish = useCallback((shark: Position, fishes: Position[]): Position | null => { - if (fishes.length === 0) return null - - return fishes.reduce((nearest, current) => { - const distToCurrent = Math.hypot(current.x - shark.x, current.y - shark.y) - const distToNearest = Math.hypot(nearest.x - shark.x, nearest.y - shark.y) - return distToCurrent < distToNearest ? current : nearest - }) - }, []) - - // Move predator towards target - const moveTowards = (predator: PredatorState, target: Position): PredatorState => { - const dx = target.x - predator.x - const dy = target.y - predator.y - const distance = Math.hypot(dx, dy) - - if (distance < 1) return predator + const findNearestFish = useCallback( + (shark: Position, fishes: Position[]): Position | null => { + if (fishes.length === 0) return null; + return fishes.reduce((nearest, current) => { + const distToCurrent = Math.hypot( + current.x - shark.x, + current.y - shark.y + ); + const distToNearest = Math.hypot( + nearest.x - shark.x, + nearest.y - shark.y + ); + return distToCurrent < distToNearest ? current : nearest; + }); + }, + [] + ); + const moveTowards = ( + predator: PredatorState, + target: Position + ): PredatorState => { + const dx = target.x - predator.x; + const dy = target.y - predator.y; + const distance = Math.hypot(dx, dy); + if (distance < 1) return predator; return { x: predator.x + (dx / distance) * predator.speed, y: predator.y + (dy / distance) * predator.speed, direction: dx > 0 ? 1 : -1, speed: predator.speed, - } - } - - // Make whale shark protect nearby fish by pushing shark away - const protectFish = useCallback((whaleShark: Position, shark: PredatorState, fishes: FishState[]): PredatorState => { - // Find closest fish to shark - const nearestFish = findNearestFish(shark, fishes) - if (!nearestFish) return shark + }; + }; - const sharkToFish = Math.hypot(nearestFish.x - shark.x, nearestFish.y - shark.y) - const whaleToShark = Math.hypot(whaleShark.x - shark.x, whaleShark.y - shark.y) - - // If shark is close to a fish and whale is close enough to intervene - if (sharkToFish < 150 && whaleToShark < 100) { - // Slap the shark away with more force - const angle = Math.atan2(shark.y - whaleShark.y, shark.x - whaleShark.x) - const slappedShark = { - ...shark, - x: shark.x + Math.cos(angle) * 250, // Longer distance - y: shark.y + Math.sin(angle) * 250, - direction: Math.cos(angle) > 0 ? 1 : -1, + const protectFish = useCallback( + ( + whaleShark: Position, + shark: PredatorState, + fishes: FishState[] + ): PredatorState => { + const nearestFish = findNearestFish(shark, fishes); + if (!nearestFish) return shark; + const sharkToFish = Math.hypot( + nearestFish.x - shark.x, + nearestFish.y - shark.y + ); + const whaleToShark = Math.hypot( + whaleShark.x - shark.x, + whaleShark.y - shark.y + ); + if (sharkToFish < 150 && whaleToShark < 100) { + const angle = Math.atan2( + shark.y - whaleShark.y, + shark.x - whaleShark.x + ); + return { + ...shark, + x: shark.x + Math.cos(angle) * 250, + y: shark.y + Math.sin(angle) * 250, + direction: Math.cos(angle) > 0 ? 1 : -1, + speed: shark.speed, + }; } - return slappedShark - } - return shark - }, [findNearestFish]) + return shark; + }, + [findNearestFish] + ); useEffect(() => { const interval = setInterval(() => { - setFishes(prevFishes => prevFishes.map(fish => { - // Return dying fish without any movement updates - if (fish.isDying) { - return fish - } - - let newX = fish.x + fish.speedX - let newY = fish.y + fish.speedY - let newDirection = fish.direction - - // Keep fish within bounds - const newXConstrained = Math.max(0, Math.min(newX, window.innerWidth - 40)) - const newYConstrained = Math.max(0, Math.min(newY, window.innerHeight - 40)) - - // Change direction if hitting walls - if (newXConstrained !== newX) { - newDirection *= -1 - } - - // Update position to constrained values - newX = newXConstrained - newY = newYConstrained - - // More gentle speed adjustment based on distance to shark - const distToShark = Math.hypot(shark.x - newX, shark.y - newY) - let speedMultiplier = 1 - if (distToShark < 200) { - // Smooth easing function for speed increase - const normalizedDist = distToShark / 200 - const easeOutQuad = 1 - normalizedDist * normalizedDist - speedMultiplier = 1 + (MAX_FISH_SPEED_MULTIPLIER - 1) * easeOutQuad - } - - // Apply speed multiplier to base speeds, not current speeds - const adjustedSpeedX = (fish.speedX / Math.abs(fish.speedX)) * BASE_FISH_SPEED * speedMultiplier - const adjustedSpeedY = (fish.speedY / Math.abs(fish.speedY || 1)) * BASE_FISH_SPEED * 0.5 * speedMultiplier - - return { - ...fish, - x: newX, - y: newY, - direction: newDirection, - speedX: adjustedSpeedX, - speedY: adjustedSpeedY, - } - })) + setFishes((prevFishes) => + prevFishes.map((fish) => { + if (fish.isDying) return fish; + let newX = fish.x + fish.speedX; + let newY = fish.y + fish.speedY; + let newDirection = fish.direction; + const newXConstrained = Math.max( + 0, + Math.min(newX, window.innerWidth - 40) + ); + const newYConstrained = Math.max( + 0, + Math.min(newY, window.innerHeight - 40) + ); + if (newXConstrained !== newX) { + newDirection *= -1; + } + newX = newXConstrained; + newY = newYConstrained; + const distToShark = Math.hypot(shark.x - newX, shark.y - newY); + let speedMultiplier = 1; + if (distToShark < 200) { + const normalizedDist = distToShark / 200; + const easeOutQuad = 1 - normalizedDist * normalizedDist; + speedMultiplier = 1 + (MAX_FISH_SPEED_MULTIPLIER - 1) * easeOutQuad; + } + const adjustedSpeedX = + (fish.speedX / Math.abs(fish.speedX)) * + BASE_FISH_SPEED * + speedMultiplier; + const adjustedSpeedY = + (fish.speedY / Math.abs(fish.speedY || 1)) * + BASE_FISH_SPEED * + 0.5 * + speedMultiplier; + return { + ...fish, + x: newX, + y: newY, + direction: newDirection, + speedX: adjustedSpeedX, + speedY: adjustedSpeedY, + }; + }) + ); - // Update shark position with bounds checking - setShark(prevShark => { - const nearestFish = findNearestFish(prevShark, fishes) - let newShark = prevShark + setShark((prevShark) => { + const nearestFish = findNearestFish(prevShark, fishes); + let newShark = prevShark; if (nearestFish) { - newShark = moveTowards(prevShark, nearestFish) + newShark = moveTowards(prevShark, nearestFish); } - newShark = protectFish(whaleShark, newShark, fishes) - - // Keep shark within bounds + newShark = protectFish(whaleShark, newShark, fishes); return { ...newShark, x: Math.max(0, Math.min(newShark.x, window.innerWidth - 60)), y: Math.max(0, Math.min(newShark.y, window.innerHeight - 60)), - } - }) - - // Update whale shark position with bounds checking - setWhaleShark(prevWhaleShark => { - const nearestFish = findNearestFish(shark, fishes) - let newWhaleShark = prevWhaleShark + }; + }); - if (nearestFish && Math.hypot(nearestFish.x - shark.x, nearestFish.y - shark.y) < 150) { - newWhaleShark = moveTowards(prevWhaleShark, shark) + setWhaleShark((prevWhaleShark) => { + const nearestFish = findNearestFish(shark, fishes); + let newWhaleShark = prevWhaleShark; + if ( + nearestFish && + Math.hypot(nearestFish.x - shark.x, nearestFish.y - shark.y) < 150 + ) { + newWhaleShark = moveTowards(prevWhaleShark, shark); } else { - // Patrol pattern newWhaleShark = { ...prevWhaleShark, x: prevWhaleShark.x + Math.cos(Date.now() / 2000) * 2, y: prevWhaleShark.y + Math.sin(Date.now() / 1500) * 2, direction: Math.cos(Date.now() / 2000) > 0 ? 1 : -1, - } + }; } - - // Keep whale shark within bounds return { ...newWhaleShark, x: Math.max(0, Math.min(newWhaleShark.x, window.innerWidth - 80)), y: Math.max(0, Math.min(newWhaleShark.y, window.innerHeight - 80)), - } - }) + }; + }); - // Check for collisions and update fish - setFishes(prevFishes => { - // First check collisions - const updatedFishes = prevFishes.map(fish => { - if (fish.isDying) return fish - - // Check if shark is close enough and moving towards the fish - const dx = fish.x - shark.x - const dy = fish.y - shark.y - const distance = Math.hypot(dx, dy) - - if (distance < 30) { // Close attack range - const sharkMovingTowardsFish = ( - (dx > 0 && shark.direction > 0) || // Fish is to right and shark facing right - (dx < 0 && shark.direction < 0) // Fish is to left and shark facing left - ) - + setFishes((prevFishes) => { + const updatedFishes = prevFishes.map((fish) => { + if (fish.isDying) return fish; + const dx = fish.x - shark.x; + const dy = fish.y - shark.y; + const distance = Math.hypot(dx, dy); + if (distance < 30) { + const sharkMovingTowardsFish = + (dx > 0 && shark.direction > 0) || + (dx < 0 && shark.direction < 0); if (sharkMovingTowardsFish) { - return { ...fish, isBeingEaten: true } + return { ...fish, isBeingEaten: true }; } - } else if (fish.isBeingEaten) { // Shark just moved away after attack - return { ...fish, isBeingEaten: false, isDying: true, dyingStartTime: Date.now() } + } else if (fish.isBeingEaten) { + return { + ...fish, + isBeingEaten: false, + isDying: true, + dyingStartTime: Date.now(), + }; } - return fish - }) - - // Then remove fish that have completed their death animation - return updatedFishes.filter(fish => { - if (!fish.isDying) return true - const timeSinceDeath = Date.now() - fish.dyingStartTime! - return timeSinceDeath < 1000 - }) - }) - }, 50) + return fish; + }); + return updatedFishes.filter((fish) => { + if (!fish.isDying) return true; + const timeSinceDeath = Date.now() - fish.dyingStartTime!; + return timeSinceDeath < 1000; + }); + }); + }, 50); - return () => clearInterval(interval) - }, [fishes, shark, whaleShark, protectFish, findNearestFish]) + return () => clearInterval(interval); + }, [fishes, shark, whaleShark, protectFish, findNearestFish]); return (
- {fishes.map(fish => ( + {/* Render the extra underwater decorations behind the fish */} + + {fishes.map((fish) => ( { isBeingEaten={fish.isBeingEaten} /> ))} - +
- ) -} + ); +}; diff --git a/showcase/fishies/src/components/Jellyfish.tsx b/showcase/fishies/src/components/Jellyfish.tsx new file mode 100644 index 0000000..866440d --- /dev/null +++ b/showcase/fishies/src/components/Jellyfish.tsx @@ -0,0 +1,22 @@ +// src/components/Jellyfish.tsx +import { CSSProperties } from "react"; + +interface JellyfishProps { + x: number; + y: number; + size?: number; +} + +export const Jellyfish: React.FC = ({ x, y, size = 40 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + // Render behind the fish and predators + zIndex: 0, + animation: "jellyfish-float 6s ease-in-out infinite", + }; + + return
🪼
; +}; diff --git a/showcase/fishies/src/components/Seashell.tsx b/showcase/fishies/src/components/Seashell.tsx new file mode 100644 index 0000000..5136941 --- /dev/null +++ b/showcase/fishies/src/components/Seashell.tsx @@ -0,0 +1,20 @@ +// src/components/Seashell.tsx +import { CSSProperties } from "react"; + +interface SeashellProps { + x: number; + y: number; + size?: number; +} + +export const Seashell: React.FC = ({ x, y, size = 30 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 0, + }; + + return
🐚
; +}; diff --git a/showcase/fishies/src/components/Seaweed.tsx b/showcase/fishies/src/components/Seaweed.tsx new file mode 100644 index 0000000..5e1e1f9 --- /dev/null +++ b/showcase/fishies/src/components/Seaweed.tsx @@ -0,0 +1,21 @@ +// src/components/Seaweed.tsx +import { CSSProperties } from "react"; + +interface SeaweedProps { + x: number; + y: number; + size?: number; +} + +export const Seaweed: React.FC = ({ x, y, size = 50 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 0, + animation: "sway 4s ease-in-out infinite", + }; + + return
🌿
; +}; diff --git a/showcase/fishies/src/components/Shark.tsx b/showcase/fishies/src/components/Shark.tsx index abead56..0288433 100644 --- a/showcase/fishies/src/components/Shark.tsx +++ b/showcase/fishies/src/components/Shark.tsx @@ -1,24 +1,26 @@ -import { CSSProperties } from 'react' +// src/components/Shark.tsx +import { CSSProperties } from "react"; interface SharkProps { - x: number - y: number - direction: number + x: number; + y: number; + direction: number; } export const Shark: React.FC = ({ x, y, direction }) => { const style: CSSProperties = { - position: 'absolute', + position: "absolute", left: `${x}px`, top: `${y}px`, + zIndex: 1, transform: ` translate3d(0, 0, ${Math.sin(Date.now() / 1200) * 300}px) rotateY(${direction > 0 ? 0 : 180}deg) scale(${1 + Math.sin(Date.now() / 1200) * 0.15}) `, - transition: 'all 0.3s ease-in-out', - fontSize: '40px', // Bigger than fish - } + transition: "all 0.3s ease-in-out", + fontSize: "40px", // Bigger than fish + }; - return
🦈
-} + return
🦈
; +}; diff --git a/showcase/fishies/src/components/UnderwaterDecorations.tsx b/showcase/fishies/src/components/UnderwaterDecorations.tsx new file mode 100644 index 0000000..95769b7 --- /dev/null +++ b/showcase/fishies/src/components/UnderwaterDecorations.tsx @@ -0,0 +1,86 @@ +// src/components/UnderwaterDecorations.tsx +import { useState } from "react"; +import { Jellyfish } from "./Jellyfish"; +import { Bubble } from "./Bubble"; +import { Coral } from "./Coral"; +import { Seashell } from "./Seashell"; +import { Seaweed } from "./Seaweed"; + +export const UnderwaterDecorations: React.FC = () => { + // Randomly position a few jellyfish near the top half + const [jellyfish] = useState(() => + Array.from({ length: 3 }, (_, i) => ({ + id: i, + x: Math.random() * window.innerWidth * 0.9, + y: Math.random() * window.innerHeight * 0.5, + size: 40 + Math.random() * 20, + })) + ); + + // Create several bubbles that start near the bottom and animate upward + const [bubbles] = useState(() => + Array.from({ length: 15 }, (_, i) => ({ + id: i, + x: Math.random() * window.innerWidth, + y: window.innerHeight - Math.random() * 100, + size: 5 + Math.random() * 10, + duration: 3 + Math.random() * 3, + })) + ); + + // Place a few corals along the bottom + const [corals] = useState(() => + Array.from({ length: 5 }, (_, i) => ({ + id: i, + x: Math.random() * (window.innerWidth - 80), + y: window.innerHeight - 80, + size: 40 + Math.random() * 20, + })) + ); + + // And a few seashells at the bottom + const [seashells] = useState(() => + Array.from({ length: 3 }, (_, i) => ({ + id: i, + x: Math.random() * (window.innerWidth - 60), + y: window.innerHeight - 60, + size: 30 + Math.random() * 10, + })) + ); + + // Add some seaweed that gently sways + const [seaweeds] = useState(() => + Array.from({ length: 4 }, (_, i) => ({ + id: i, + x: Math.random() * (window.innerWidth - 80), + y: window.innerHeight - 120, + size: 50 + Math.random() * 20, + })) + ); + + return ( + <> + {jellyfish.map((j) => ( + + ))} + {bubbles.map((b) => ( + + ))} + {corals.map((c) => ( + + ))} + {seashells.map((s) => ( + + ))} + {seaweeds.map((sw) => ( + + ))} + + ); +}; diff --git a/showcase/fishies/src/components/WhaleShark.tsx b/showcase/fishies/src/components/WhaleShark.tsx index 7ac6cc5..c9188ad 100644 --- a/showcase/fishies/src/components/WhaleShark.tsx +++ b/showcase/fishies/src/components/WhaleShark.tsx @@ -1,24 +1,26 @@ -import { CSSProperties } from 'react' +// src/components/WhaleShark.tsx +import { CSSProperties } from "react"; interface WhaleSharkProps { - x: number - y: number - direction: number + x: number; + y: number; + direction: number; } export const WhaleShark: React.FC = ({ x, y, direction }) => { const style: CSSProperties = { - position: 'absolute', + position: "absolute", left: `${x}px`, top: `${y}px`, + zIndex: 1, transform: ` translate3d(0, 0, ${Math.sin(Date.now() / 1500) * 400}px) rotateY(${direction > 0 ? 0 : 180}deg) scale(${1 + Math.sin(Date.now() / 1500) * 0.2}) `, - transition: 'all 0.3s ease-in-out', - fontSize: '64px', // Much bigger than shark - } + transition: "all 0.3s ease-in-out", + fontSize: "64px", // Much bigger than shark + }; - return
🐋
-} + return
🐋
; +}; From 1fd8d46310e8f29686278e02764632100bc0eb90 Mon Sep 17 00:00:00 2001 From: Brandon Chen Date: Fri, 31 Jan 2025 14:14:31 -0800 Subject: [PATCH 19/34] feat: even moar fishies --- showcase/fishies/knowledge.md | 62 ++- showcase/fishies/src/App.css | 166 +++++++- showcase/fishies/src/components/Crab.tsx | 20 + showcase/fishies/src/components/Dolphin.tsx | 24 ++ showcase/fishies/src/components/Fish.tsx | 4 +- showcase/fishies/src/components/FishTank.tsx | 385 +++++++++++++++--- .../fishies/src/components/FoodPellet.tsx | 26 ++ showcase/fishies/src/components/Jellyfish.tsx | 7 +- showcase/fishies/src/components/Plankton.tsx | 28 ++ .../fishies/src/components/RippleEffect.tsx | 23 ++ .../fishies/src/components/SeaSparkle.tsx | 29 ++ showcase/fishies/src/components/SeaTurtle.tsx | 20 + showcase/fishies/src/components/Starfish.tsx | 21 + .../src/components/TerritorialCrab.tsx | 28 ++ .../src/components/UnderwaterDecorations.tsx | 143 ++++++- showcase/fishies/src/types.ts | 16 + 16 files changed, 880 insertions(+), 122 deletions(-) create mode 100644 showcase/fishies/src/components/Crab.tsx create mode 100644 showcase/fishies/src/components/Dolphin.tsx create mode 100644 showcase/fishies/src/components/FoodPellet.tsx create mode 100644 showcase/fishies/src/components/Plankton.tsx create mode 100644 showcase/fishies/src/components/RippleEffect.tsx create mode 100644 showcase/fishies/src/components/SeaSparkle.tsx create mode 100644 showcase/fishies/src/components/SeaTurtle.tsx create mode 100644 showcase/fishies/src/components/Starfish.tsx create mode 100644 showcase/fishies/src/components/TerritorialCrab.tsx create mode 100644 showcase/fishies/src/types.ts diff --git a/showcase/fishies/knowledge.md b/showcase/fishies/knowledge.md index fc36144..a807397 100644 --- a/showcase/fishies/knowledge.md +++ b/showcase/fishies/knowledge.md @@ -12,46 +12,42 @@ A fish tank simulation with swimming fish, predator behavior, and interactive el ## Animation Guidelines - Use CSS transitions for smooth movement -- Use 3D transforms for depth: - - Container needs perspective: 2000px - - Container needs transform-style: preserve-3d - - Fish: ±200px depth, fast cycle - - Shark: ±300px depth, medium cycle - - Whale shark: ±400px depth, slow cycle -- Scale with depth for more dramatic effect: - - Fish: ±10% scale - - Shark: ±15% scale - - Whale shark: ±20% scale -- Use rotateY instead of scaleX for direction changes -- Remove transitions for immediate reactions to events -- Add depth to environment: - - Use transparent gradient layers in background - - Animate container with subtle 3D movement - - Create parallax effect with container animation -- Death animation sequence: - 1. Fish straightens out when shark attacks - 2. When shark moves away, fish flips upside down - 3. After 500ms, transforms to skull (☠️) and starts fading - 4. Completes fade out over next 500ms -- Scale emojis for different creature sizes +- Use 3D transforms for depth +- Scale with depth for dramatic effect +- Use rotateY for direction changes +- Remove transitions for immediate reactions ## Combat Mechanics -- Shark must be moving towards fish to attack (within 30px range) -- Fish speed increases based on distance to shark using quadratic easing -- Whale shark protects fish by pushing shark away when nearby +- Shark must be moving towards fish to attack +- Fish speed increases near predators +- Whale shark protects fish from sharks ## Game Balance -- Base fish speed: 0.5 units (slow peaceful swimming) -- Shark speed: 3 units (fast predator) -- Whale shark speed: 4 units (fast enough to catch shark) -- Fish speed multiplier: gradually increases up to 2x within 200px of shark -- Protection distances: - - Shark catching fish: 15px (must be within 15 degrees of directly facing fish) - - Whale shark slaps shark away 250px when within 100px range +- Base fish speed: 0.5 units +- Shark speed: 3 units +- Whale shark speed: 4 units +- Protection radius: 100px for whale shark + +## Interactive Elements +- Click for bubbles +- Shift+click for food +- Ctrl/Cmd+click for sparkles +- Ripple effects under fast predators + +## Fish Behavior +- School with nearby fish +- Avoid predators +- Seek food +- Hide near decorations when threatened + +## Ecosystem Interactions +- Predator competition +- Safe zones near decorations +- Territorial behaviors +- Water current effects ## Verifying changes After every change, run: ```bash npm run lint && npm run typecheck ``` -This will check for lint issues and type errors. diff --git a/showcase/fishies/src/App.css b/showcase/fishies/src/App.css index 4ca17cb..4871983 100644 --- a/showcase/fishies/src/App.css +++ b/showcase/fishies/src/App.css @@ -5,6 +5,9 @@ background: linear-gradient(180deg, #0f4c81 0%, #1e90ff 50%, #0d3b66 100%); perspective: 2000px; transform-style: preserve-3d; + 0% { transform: translate3d(0, 0, 0) scale(1); } + 50% { transform: translate3d(20px, -30px, 100px) scale(1.3) rotate(10deg); } + 100% { transform: translate3d(0, 0, 0) scale(1); } } /* The fish-tank container holds all moving parts */ @@ -12,7 +15,39 @@ width: 100%; height: 100%; position: relative; - animation: tank-depth 20s infinite ease-in-out; + animation: tank-depth 20s infinite ease-in-out, tank-current 10s ease-in-out infinite; + cursor: pointer; +} + +/* Caustics overlay for dynamic lighting */ +.caustics-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 0; + background: radial-gradient( + circle at 50% 50%, + rgba(255, 255, 255, 0.05), + transparent 60% + ); + opacity: 0.7; + animation: caustics 8s ease-in-out infinite alternate; +} + +/* Ambient light overlay */ +.ambient-light { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 0; + background: linear-gradient(45deg, rgba(255,255,255,0.05), transparent); + animation: ambient-light-move 15s ease-in-out infinite; } /* Subtle light-ray overlay for extra depth */ @@ -33,44 +68,149 @@ } @keyframes tank-depth { - 0%, - 100% { - transform: translate3d(0, 0, 0); + 0%, 100% { + transform: translate3d(0, 0, 0) rotate3d(1, 1, 0, 0deg); } 50% { - transform: translate3d(50px, 30px, -200px); + transform: translate3d(50px, 30px, -200px) rotate3d(1, 1, 0, 3deg); } } +@keyframes tank-current { + 0%, 100% { transform: translate3d(0, 0, 0); } + 50% { transform: translate3d(10px, -5px, 0); } +} + @keyframes jellyfish-float { 0% { - transform: translate(0, 0) rotate(0deg); + transform: translate3d(0, 0, 0) rotate(0deg) scale(1); + } + 50% { + transform: translate3d(10px, -20px, 100px) rotate(5deg) scale(1.1); + } + 100% { + transform: translate3d(0, 0, 0) rotate(0deg) scale(1); + } +} + +@keyframes jellyfish-playful { + 0% { + transform: translate3d(0, 0, 0) rotate(0deg) scale(1); } 50% { - transform: translate(10px, -20px) rotate(5deg); + transform: translate3d(10px, -20px, 100px) rotate(5deg) scale(1.1); } 100% { - transform: translate(0, 0) rotate(0deg); + transform: translate3d(0, 0, 0) rotate(0deg) scale(1); } } @keyframes bubble-rise { 0% { - transform: translateY(0) scale(1); + transform: translate3d(0, 0, 0) scale(1); opacity: 1; } 100% { - transform: translateY(-100px) scale(0.5); + transform: translate3d(var(--drift-x, 20px), -100px, 50px) scale(0.5); opacity: 0; } } @keyframes sway { - 0%, - 100% { + 0%, 100% { + transform: rotate(0deg) translate3d(0, 0, 20px); + } + 50% { + transform: rotate(5deg) translate3d(0, 0, 40px); + } +} + +@keyframes starfish-rotate { + 0% { transform: rotate(0deg); } + 100% { + transform: rotate(15deg); + } +} + +@keyframes crab-walk { + 0% { + transform: translate3d(0, 0, 10px) rotate(-2deg); + } + 25% { + transform: translate3d(5px, 0, 10px) rotate(0deg); + } + 75% { + transform: translate3d(-5px, 0, 10px) rotate(0deg); + } + 100% { + transform: translate3d(0, 0, 10px) rotate(-2deg); + } +} + +@keyframes caustics { + 0% { + transform: translate3d(0, 0, 0); + opacity: 0.7; + } 50% { - transform: rotate(5deg); + transform: translate3d(10px, -10px, 0); + opacity: 0.8; + } + 100% { + transform: translate3d(-10px, 10px, 0); + opacity: 0.7; + } +} + +@keyframes ambient-light-move { + 0% { transform: translate(0, 0); } + 50% { transform: translate(20px, 20px); } + 100% { transform: translate(0, 0); } +} + +@keyframes food-pulse { + 0%, 100% { transform: scale(1); opacity: 1; } + 50% { transform: scale(1.2); opacity: 0.8; } +} + +@keyframes water-ripple { + 0% { transform: scale(0); opacity: 0.5; } + 100% { transform: scale(4); opacity: 0; } +} + +@keyframes plankton-drift { + 0% { transform: translate(0, 0); opacity: 0; } + 50% { opacity: 1; } + 100% { transform: translate(50px, -50px); opacity: 0; } +} + +@keyframes turtle-swim { + 0% { transform: translate3d(0, 0, 0) rotate(0deg); } + 50% { transform: translate3d(20px, -10px, 50px) rotate(5deg); } + 100% { transform: translate3d(0, 0, 0) rotate(0deg); } +} + +@keyframes dolphin-swim { + 0% { + transform: translate3d(0, 0, 0) rotate(0deg); + } + 50% { + transform: translate3d(20px, -10px, 50px) rotate(5deg); + } + 100% { + transform: translate3d(0, 0, 0) rotate(0deg); + } +} + +@keyframes sparkle-fade { + 0% { + transform: scale(0.5); + opacity: 1; + } + 100% { + transform: scale(1.5); + opacity: 0; } } diff --git a/showcase/fishies/src/components/Crab.tsx b/showcase/fishies/src/components/Crab.tsx new file mode 100644 index 0000000..d13e78b --- /dev/null +++ b/showcase/fishies/src/components/Crab.tsx @@ -0,0 +1,20 @@ +import { CSSProperties } from "react"; + +interface CrabProps { + x: number; + y: number; + size?: number; +} + +export const Crab: React.FC = ({ x, y, size = 40 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 0, + animation: "crab-walk 4s linear infinite", + }; + + return
🦀
; +}; diff --git a/showcase/fishies/src/components/Dolphin.tsx b/showcase/fishies/src/components/Dolphin.tsx new file mode 100644 index 0000000..1db2f74 --- /dev/null +++ b/showcase/fishies/src/components/Dolphin.tsx @@ -0,0 +1,24 @@ +import { CSSProperties } from "react"; + +interface DolphinProps { + x: number; + y: number; + size?: number; +} + +export const Dolphin: React.FC = ({ x, y, size = 40 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 1, + transform: ` + translate3d(0, 0, ${Math.sin(Date.now() / 2500) * 150}px) + rotateY(${Math.random() < 0.5 ? 0 : 180}deg) + `, + animation: "dolphin-swim 6s ease-in-out infinite", + }; + + return
🐬
; +}; diff --git a/showcase/fishies/src/components/Fish.tsx b/showcase/fishies/src/components/Fish.tsx index 8146645..889c5f4 100644 --- a/showcase/fishies/src/components/Fish.tsx +++ b/showcase/fishies/src/components/Fish.tsx @@ -9,6 +9,7 @@ interface FishProps { isDying?: boolean; dyingStartTime?: number; isBeingEaten?: boolean; + isHiding?: boolean; } export const Fish: React.FC = ({ @@ -19,6 +20,7 @@ export const Fish: React.FC = ({ isDying, dyingStartTime, isBeingEaten, + isHiding, }) => { const style: CSSProperties = { position: "absolute", @@ -41,7 +43,7 @@ export const Fish: React.FC = ({ transition: isDying ? "opacity 1s ease-out" : "none", fontSize: "24px", color, - opacity: isDying ? (Date.now() - dyingStartTime! > 500 ? 0 : 1) : 1, + opacity: isDying ? (Date.now() - dyingStartTime! > 500 ? 0 : 1) : isHiding ? 0.6 : 1, }; return ( diff --git a/showcase/fishies/src/components/FishTank.tsx b/showcase/fishies/src/components/FishTank.tsx index 67394e5..2172ba1 100644 --- a/showcase/fishies/src/components/FishTank.tsx +++ b/showcase/fishies/src/components/FishTank.tsx @@ -1,16 +1,19 @@ -// src/components/FishTank.tsx -import { useEffect, useState, useCallback } from "react"; +import { useEffect, useState, useCallback, useRef } from "react"; import { Fish } from "./Fish"; import { Shark } from "./Shark"; import { WhaleShark } from "./WhaleShark"; import { UnderwaterDecorations } from "./UnderwaterDecorations"; +import { Bubble } from "./Bubble"; +import { FoodPellet } from "./FoodPellet"; +import { RippleEffect } from "./RippleEffect"; +import { SeaSparkle } from "./SeaSparkle"; interface Position { x: number; y: number; } -interface FishState extends Position { +export interface FishState extends Position { id: number; direction: number; color: string; @@ -19,6 +22,7 @@ interface FishState extends Position { isDying?: boolean; dyingStartTime?: number; isBeingEaten?: boolean; + isHiding?: boolean; } interface PredatorState extends Position { @@ -26,15 +30,65 @@ interface PredatorState extends Position { speed: number; } +interface InteractiveBubble { + id: number; + x: number; + y: number; + size: number; + duration: number; +} + +interface RippleState { + id: number; + x: number; + y: number; +} + +interface FoodPelletState { + id: number; + x: number; + y: number; + size: number; + duration: number; +} + +interface InteractiveSparkle { + id: number; + x: number; + y: number; + size: number; + duration: number; +} + const COLORS = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEEAD"]; const SHARK_SPEED = 3; const WHALE_SHARK_SPEED = 4; const BASE_FISH_SPEED = 0.5; const MAX_FISH_SPEED_MULTIPLIER = 1.5; +const COMPETITION_DISTANCE = 50; +const COMPETITION_REPULSION = 0.1; +const DANGER_DISTANCE = 100; + +// Define safe zones near decorations +const SAFE_ZONES: Position[] = [ + { x: 80, y: window.innerHeight - 100 }, + { x: 300, y: window.innerHeight - 120 }, + { x: 600, y: window.innerHeight - 90 }, + { x: 800, y: window.innerHeight - 110 }, +]; + +const findNearestSafeZone = (fish: Position): Position | null => { + if (SAFE_ZONES.length === 0) return null; + return SAFE_ZONES.reduce((closest, zone) => { + const dZone = Math.hypot(zone.x - fish.x, zone.y - fish.y); + const dClosest = Math.hypot(closest.x - fish.x, closest.y - fish.y); + return dZone < dClosest ? zone : closest; + }, SAFE_ZONES[0]); +}; export const FishTank: React.FC = () => { const [fishes, setFishes] = useState(() => - Array.from({ length: 10 }, (_, i) => ({ + Array.from({ length: 12 }, (_, i) => ({ id: i, x: Math.random() * window.innerWidth * 0.8, y: Math.random() * window.innerHeight * 0.8, @@ -61,28 +115,99 @@ export const FishTank: React.FC = () => { speed: WHALE_SHARK_SPEED, })); + const [interactiveBubbles, setInteractiveBubbles] = useState([]); + const [foodPellets, setFoodPellets] = useState([]); + const [ripples, setRipples] = useState([]); + const [interactiveSparkles, setInteractiveSparkles] = useState([]); + + // Refs to throttle ripple effects for predators + const sharkRippleTimeRef = useRef(0); + const whaleSharkRippleTimeRef = useRef(0); + + const handleTankClick = (e: React.MouseEvent) => { + const rect = e.currentTarget.getBoundingClientRect(); + + // If user holds Ctrl (or Command) key, spawn interactive "sea sparkles" + if (e.ctrlKey || e.metaKey) { + const sparkleCount = 3 + Math.floor(Math.random() * 3); + const newSparkles = Array.from({ length: sparkleCount }, () => ({ + id: Date.now() + Math.random(), + x: e.clientX - rect.left + (Math.random() - 0.5) * 20, + y: e.clientY - rect.top + (Math.random() - 0.5) * 20, + size: 12 + Math.random() * 8, + duration: 1 + Math.random(), + })); + setInteractiveSparkles((prev) => [...prev, ...newSparkles]); + newSparkles.forEach((sparkle) => { + setTimeout(() => { + setInteractiveSparkles((prev) => + prev.filter((s) => s.id !== sparkle.id) + ); + }, sparkle.duration * 1000); + }); + return; + } + + // Create a ripple effect unless it's a food pellet drop + if (!e.shiftKey) { + const ripple = { + id: Date.now() + Math.random(), + x: e.clientX - rect.left, + y: e.clientY - rect.top, + }; + setRipples((prev) => [...prev, ripple]); + setTimeout(() => { + setRipples((prev) => prev.filter((r) => r.id !== ripple.id)); + }, 1000); + } + + if (e.shiftKey) { + const pellet = { + id: Date.now() + Math.random(), + x: e.clientX - rect.left, + y: e.clientY - rect.top, + size: 16, + duration: 10000, + }; + setFoodPellets((prev) => [...prev, pellet]); + setTimeout(() => { + setFoodPellets((prev) => prev.filter((p) => p.id !== pellet.id)); + }, pellet.duration); + } else { + const bubbleCount = 3 + Math.floor(Math.random() * 3); + const newBubbles = Array.from({ length: bubbleCount }, () => ({ + id: Date.now() + Math.random(), + x: e.clientX - rect.left + (Math.random() - 0.5) * 20, + y: e.clientY - rect.top + (Math.random() - 0.5) * 20, + size: 8 + Math.random() * 12, + duration: 2 + Math.random() * 2, + })); + + setInteractiveBubbles((prev) => [...prev, ...newBubbles]); + + newBubbles.forEach((bubble) => { + setTimeout(() => { + setInteractiveBubbles((prev) => + prev.filter((b) => b.id !== bubble.id) + ); + }, bubble.duration * 1000); + }); + } + }; + const findNearestFish = useCallback( - (shark: Position, fishes: Position[]): Position | null => { + (predator: Position, fishes: Position[]): Position | null => { if (fishes.length === 0) return null; return fishes.reduce((nearest, current) => { - const distToCurrent = Math.hypot( - current.x - shark.x, - current.y - shark.y - ); - const distToNearest = Math.hypot( - nearest.x - shark.x, - nearest.y - shark.y - ); + const distToCurrent = Math.hypot(current.x - predator.x, current.y - predator.y); + const distToNearest = Math.hypot(nearest.x - predator.x, nearest.y - predator.y); return distToCurrent < distToNearest ? current : nearest; }); }, [] ); - const moveTowards = ( - predator: PredatorState, - target: Position - ): PredatorState => { + const moveTowards = (predator: PredatorState, target: Position): PredatorState => { const dx = target.x - predator.x; const dy = target.y - predator.y; const distance = Math.hypot(dx, dy); @@ -96,26 +221,13 @@ export const FishTank: React.FC = () => { }; const protectFish = useCallback( - ( - whaleShark: Position, - shark: PredatorState, - fishes: FishState[] - ): PredatorState => { + (whaleShark: Position, shark: PredatorState, fishes: FishState[]): PredatorState => { const nearestFish = findNearestFish(shark, fishes); if (!nearestFish) return shark; - const sharkToFish = Math.hypot( - nearestFish.x - shark.x, - nearestFish.y - shark.y - ); - const whaleToShark = Math.hypot( - whaleShark.x - shark.x, - whaleShark.y - shark.y - ); + const sharkToFish = Math.hypot(nearestFish.x - shark.x, nearestFish.y - shark.y); + const whaleToShark = Math.hypot(whaleShark.x - shark.x, whaleShark.y - shark.y); if (sharkToFish < 150 && whaleToShark < 100) { - const angle = Math.atan2( - shark.y - whaleShark.y, - shark.x - whaleShark.x - ); + const angle = Math.atan2(shark.y - whaleShark.y, shark.x - whaleShark.x); return { ...shark, x: shark.x + Math.cos(angle) * 250, @@ -131,25 +243,108 @@ export const FishTank: React.FC = () => { useEffect(() => { const interval = setInterval(() => { + // Global subtle current offsets (very gentle drift) + const currentX = Math.sin(Date.now() / 2000) * 0.5; + const currentY = Math.cos(Date.now() / 2000) * 0.5; + setFishes((prevFishes) => prevFishes.map((fish) => { if (fish.isDying) return fish; - let newX = fish.x + fish.speedX; - let newY = fish.y + fish.speedY; + let newSpeedX = fish.speedX; + let newSpeedY = fish.speedY; + + // Check for nearby predators and seek safety + // Check for predator proximity + const distToPredators = { + shark: Math.hypot(fish.x - shark.x, fish.y - shark.y), + whaleShark: Math.hypot(fish.x - whaleShark.x, fish.y - whaleShark.y) + }; + + if (distToPredators.shark < DANGER_DISTANCE || distToPredators.whaleShark < DANGER_DISTANCE) { + const safeZone = findNearestSafeZone(fish); + if (safeZone) { + const dirX = safeZone.x - fish.x; + const dirY = safeZone.y - fish.y; + const norm = Math.hypot(dirX, dirY) || 1; + newSpeedX = (dirX / norm) * BASE_FISH_SPEED * 2; // Faster when seeking safety + newSpeedY = (dirY / norm) * BASE_FISH_SPEED * 2; + fish.isHiding = true; + } + } else { + fish.isHiding = false; + } + + // Food attraction behavior + if (foodPellets.length) { + const nearestPellet = foodPellets.reduce((closest: FoodPelletState | null, pellet) => { + if (!closest) return pellet; + return Math.hypot(fish.x - pellet.x, fish.y - pellet.y) < + Math.hypot(fish.x - closest.x, fish.y - closest.y) + ? pellet + : closest; + }, null); + + if (nearestPellet) { + const dx = nearestPellet.x - fish.x; + const dy = nearestPellet.y - fish.y; + const dist = Math.hypot(dx, dy); + if (dist > 0) { + const boostFactor = 1.5; + newSpeedX = (dx / dist) * (BASE_FISH_SPEED * boostFactor); + newSpeedY = (dy / dist) * (BASE_FISH_SPEED * boostFactor); + } + if (dist < 20) { + setFoodPellets((prev) => + prev.filter((p) => p.id !== nearestPellet.id) + ); + } + } + } + + // Add a slight random jitter for natural movement + newSpeedX += (Math.random() - 0.5) * 0.05; + newSpeedY += (Math.random() - 0.5) * 0.05; + + // Calculate new position with global current offsets added + let newX = fish.x + newSpeedX + currentX; + let newY = fish.y + newSpeedY + currentY; let newDirection = fish.direction; - const newXConstrained = Math.max( - 0, - Math.min(newX, window.innerWidth - 40) - ); - const newYConstrained = Math.max( - 0, - Math.min(newY, window.innerHeight - 40) - ); + const newXConstrained = Math.max(0, Math.min(newX, window.innerWidth - 40)); + const newYConstrained = Math.max(0, Math.min(newY, window.innerHeight - 40)); if (newXConstrained !== newX) { newDirection *= -1; } newX = newXConstrained; newY = newYConstrained; + + // Schooling behavior: look for neighbors + const neighbors = prevFishes.filter( + (other) => + other.id !== fish.id && + Math.hypot(other.x - fish.x, other.y - fish.y) < 100 + ); + + if (neighbors.length > 0) { + // Alignment: average nearby velocities + const avgSpeedX = neighbors.reduce((sum, n) => sum + n.speedX, 0) / neighbors.length; + const avgSpeedY = neighbors.reduce((sum, n) => sum + n.speedY, 0) / neighbors.length; + + // Blend current speed with average (small factor) + const alignmentFactor = 0.1; + newSpeedX = newSpeedX + (avgSpeedX - newSpeedX) * alignmentFactor; + newSpeedY = newSpeedY + (avgSpeedY - newSpeedY) * alignmentFactor; + + // Separation: push away from very close neighbors + neighbors.forEach((n) => { + const d = Math.hypot(n.x - fish.x, n.y - fish.y); + if (d < 30 && d > 0) { + newSpeedX -= ((n.x - fish.x) / d) * 0.05; + newSpeedY -= ((n.y - fish.y) / d) * 0.05; + } + }); + } + + // Retain existing predator avoidance logic const distToShark = Math.hypot(shark.x - newX, shark.y - newY); let speedMultiplier = 1; if (distToShark < 200) { @@ -157,22 +352,23 @@ export const FishTank: React.FC = () => { const easeOutQuad = 1 - normalizedDist * normalizedDist; speedMultiplier = 1 + (MAX_FISH_SPEED_MULTIPLIER - 1) * easeOutQuad; } - const adjustedSpeedX = - (fish.speedX / Math.abs(fish.speedX)) * + newSpeedX = + (newSpeedX / Math.abs(newSpeedX || 1)) * BASE_FISH_SPEED * speedMultiplier; - const adjustedSpeedY = - (fish.speedY / Math.abs(fish.speedY || 1)) * + newSpeedY = + (newSpeedY / Math.abs(newSpeedY || 1)) * BASE_FISH_SPEED * 0.5 * speedMultiplier; + return { ...fish, x: newX, y: newY, direction: newDirection, - speedX: adjustedSpeedX, - speedY: adjustedSpeedY, + speedX: newSpeedX, + speedY: newSpeedY, }; }) ); @@ -184,10 +380,23 @@ export const FishTank: React.FC = () => { newShark = moveTowards(prevShark, nearestFish); } newShark = protectFish(whaleShark, newShark, fishes); + + // Add competition repulsion + const dx = newShark.x - whaleShark.x; + const dy = newShark.y - whaleShark.y; + const dist = Math.hypot(dx, dy); + if (dist < COMPETITION_DISTANCE) { + newShark = { + ...newShark, + x: newShark.x + (dx / dist) * COMPETITION_REPULSION * SHARK_SPEED, + y: newShark.y + (dy / dist) * COMPETITION_REPULSION * SHARK_SPEED, + }; + } + return { ...newShark, - x: Math.max(0, Math.min(newShark.x, window.innerWidth - 60)), - y: Math.max(0, Math.min(newShark.y, window.innerHeight - 60)), + x: Math.max(0, Math.min(newShark.x + currentX, window.innerWidth - 60)), + y: Math.max(0, Math.min(newShark.y + currentY, window.innerHeight - 60)), }; }); @@ -207,10 +416,23 @@ export const FishTank: React.FC = () => { direction: Math.cos(Date.now() / 2000) > 0 ? 1 : -1, }; } + + // Add competition repulsion + const dx = newWhaleShark.x - shark.x; + const dy = newWhaleShark.y - shark.y; + const dist = Math.hypot(dx, dy); + if (dist < COMPETITION_DISTANCE) { + newWhaleShark = { + ...newWhaleShark, + x: newWhaleShark.x + (dx / dist) * COMPETITION_REPULSION * WHALE_SHARK_SPEED, + y: newWhaleShark.y + (dy / dist) * COMPETITION_REPULSION * WHALE_SHARK_SPEED, + }; + } + return { ...newWhaleShark, - x: Math.max(0, Math.min(newWhaleShark.x, window.innerWidth - 80)), - y: Math.max(0, Math.min(newWhaleShark.y, window.innerHeight - 80)), + x: Math.max(0, Math.min(newWhaleShark.x + currentX, window.innerWidth - 80)), + y: Math.max(0, Math.min(newWhaleShark.y + currentY, window.innerHeight - 80)), }; }); @@ -246,12 +468,33 @@ export const FishTank: React.FC = () => { }, 50); return () => clearInterval(interval); - }, [fishes, shark, whaleShark, protectFish, findNearestFish]); + }, [fishes, shark, whaleShark, protectFish, findNearestFish, foodPellets]); + + // Ripple effect for fast-moving predators + useEffect(() => { + const now = Date.now(); + if (now - sharkRippleTimeRef.current > 500) { + setRipples((prev) => [...prev, { id: now + Math.random(), x: shark.x, y: shark.y }]); + sharkRippleTimeRef.current = now; + } + }, [shark.x, shark.y]); + + useEffect(() => { + const now = Date.now(); + if (now - whaleSharkRippleTimeRef.current > 500) { + setRipples((prev) => [...prev, { id: now + Math.random(), x: whaleShark.x, y: whaleShark.y }]); + whaleSharkRippleTimeRef.current = now; + } + }, [whaleShark.x, whaleShark.y]); return ( -
- {/* Render the extra underwater decorations behind the fish */} - +
+
+
+ {ripples.map((r) => ( + + ))} + {fishes.map((fish) => ( { y={whaleShark.y} direction={whaleShark.direction} /> + {interactiveBubbles.map((b) => ( + + ))} + {foodPellets.map((p) => ( + + ))} + {interactiveSparkles.map((s) => ( + + ))}
); }; diff --git a/showcase/fishies/src/components/FoodPellet.tsx b/showcase/fishies/src/components/FoodPellet.tsx new file mode 100644 index 0000000..34b2995 --- /dev/null +++ b/showcase/fishies/src/components/FoodPellet.tsx @@ -0,0 +1,26 @@ +import { CSSProperties } from "react"; + +interface FoodPelletProps { + x: number; + y: number; + size?: number; +} + +export const FoodPellet: React.FC = ({ + x, + y, + size = 16, +}) => { + const style: CSSProperties = { + position: "absolute", + left: `${x - size / 2}px`, + top: `${y - size / 2}px`, + width: `${size}px`, + height: `${size}px`, + zIndex: 1, + fontSize: `${size}px`, + animation: "food-pulse 2s ease-in-out infinite", + }; + + return
🍤
; +}; diff --git a/showcase/fishies/src/components/Jellyfish.tsx b/showcase/fishies/src/components/Jellyfish.tsx index 866440d..77c2812 100644 --- a/showcase/fishies/src/components/Jellyfish.tsx +++ b/showcase/fishies/src/components/Jellyfish.tsx @@ -5,9 +5,10 @@ interface JellyfishProps { x: number; y: number; size?: number; + isPlayful?: boolean; } -export const Jellyfish: React.FC = ({ x, y, size = 40 }) => { +export const Jellyfish: React.FC = ({ x, y, size = 40, isPlayful = false }) => { const style: CSSProperties = { position: "absolute", left: `${x}px`, @@ -15,7 +16,9 @@ export const Jellyfish: React.FC = ({ x, y, size = 40 }) => { fontSize: `${size}px`, // Render behind the fish and predators zIndex: 0, - animation: "jellyfish-float 6s ease-in-out infinite", + animation: isPlayful + ? "jellyfish-playful 3s ease-in-out infinite" + : "jellyfish-float 6s ease-in-out infinite", }; return
🪼
; diff --git a/showcase/fishies/src/components/Plankton.tsx b/showcase/fishies/src/components/Plankton.tsx new file mode 100644 index 0000000..2f337e9 --- /dev/null +++ b/showcase/fishies/src/components/Plankton.tsx @@ -0,0 +1,28 @@ +import { CSSProperties } from "react"; + +interface PlanktonProps { + x: number; + y: number; + size?: number; + duration?: number; +} + +export const Plankton: React.FC = ({ + x, + y, + size = 2, + duration = 6, +}) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + width: `${size}px`, + height: `${size}px`, + borderRadius: "50%", + backgroundColor: "rgba(255, 255, 255, 0.8)", + animation: `plankton-drift ${duration}s linear infinite`, + zIndex: 0, + }; + return
; +}; diff --git a/showcase/fishies/src/components/RippleEffect.tsx b/showcase/fishies/src/components/RippleEffect.tsx new file mode 100644 index 0000000..feeabe8 --- /dev/null +++ b/showcase/fishies/src/components/RippleEffect.tsx @@ -0,0 +1,23 @@ +import { CSSProperties } from "react"; + +interface RippleEffectProps { + x: number; + y: number; +} + +export const RippleEffect: React.FC = ({ x, y }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + width: "20px", + height: "20px", + borderRadius: "50%", + backgroundColor: "rgba(255, 255, 255, 0.2)", + transform: "translate(-50%, -50%)", + pointerEvents: "none", + animation: "water-ripple 1s ease-out forwards", + zIndex: 0, + }; + return
; +}; diff --git a/showcase/fishies/src/components/SeaSparkle.tsx b/showcase/fishies/src/components/SeaSparkle.tsx new file mode 100644 index 0000000..327d35a --- /dev/null +++ b/showcase/fishies/src/components/SeaSparkle.tsx @@ -0,0 +1,29 @@ +import { CSSProperties } from "react"; + +interface SeaSparkleProps { + x: number; + y: number; + size?: number; + duration?: number; +} + +export const SeaSparkle: React.FC = ({ + x, + y, + size = 12, + duration = 1, +}) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + width: `${size}px`, + height: `${size}px`, + fontSize: `${size}px`, + pointerEvents: "none", + animation: `sparkle-fade ${duration}s ease-out forwards`, + zIndex: 2, + }; + + return
; +}; diff --git a/showcase/fishies/src/components/SeaTurtle.tsx b/showcase/fishies/src/components/SeaTurtle.tsx new file mode 100644 index 0000000..48f583f --- /dev/null +++ b/showcase/fishies/src/components/SeaTurtle.tsx @@ -0,0 +1,20 @@ +import { CSSProperties } from "react"; + +interface SeaTurtleProps { + x: number; + y: number; + size?: number; +} + +export const SeaTurtle: React.FC = ({ x, y, size = 50 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 0, + animation: "turtle-swim 12s ease-in-out infinite", + }; + + return
🐢
; +}; diff --git a/showcase/fishies/src/components/Starfish.tsx b/showcase/fishies/src/components/Starfish.tsx new file mode 100644 index 0000000..aac5275 --- /dev/null +++ b/showcase/fishies/src/components/Starfish.tsx @@ -0,0 +1,21 @@ +import { CSSProperties } from "react"; + +interface StarfishProps { + x: number; + y: number; + size?: number; +} + +export const Starfish: React.FC = ({ x, y, size = 30 }) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 0, + transformOrigin: "center", + animation: "starfish-rotate 5s ease-in-out infinite alternate", + }; + + return
; +}; diff --git a/showcase/fishies/src/components/TerritorialCrab.tsx b/showcase/fishies/src/components/TerritorialCrab.tsx new file mode 100644 index 0000000..75e92f7 --- /dev/null +++ b/showcase/fishies/src/components/TerritorialCrab.tsx @@ -0,0 +1,28 @@ +import { CSSProperties } from "react"; + +interface TerritorialCrabProps { + x: number; + y: number; + size?: number; + intruderNearby?: boolean; +} + +export const TerritorialCrab: React.FC = ({ + x, + y, + size = 40, + intruderNearby = false, +}) => { + const style: CSSProperties = { + position: "absolute", + left: `${x}px`, + top: `${y}px`, + fontSize: `${size}px`, + zIndex: 0, + animation: intruderNearby + ? "crab-walk 2s linear infinite" // faster animation + : "crab-walk 4s linear infinite", + }; + + return
🦀
; +}; diff --git a/showcase/fishies/src/components/UnderwaterDecorations.tsx b/showcase/fishies/src/components/UnderwaterDecorations.tsx index 95769b7..9fefe26 100644 --- a/showcase/fishies/src/components/UnderwaterDecorations.tsx +++ b/showcase/fishies/src/components/UnderwaterDecorations.tsx @@ -1,25 +1,48 @@ -// src/components/UnderwaterDecorations.tsx -import { useState } from "react"; +import { useState, useEffect } from "react"; +import { type FishState } from "./FishTank"; import { Jellyfish } from "./Jellyfish"; import { Bubble } from "./Bubble"; import { Coral } from "./Coral"; import { Seashell } from "./Seashell"; import { Seaweed } from "./Seaweed"; +import { Starfish } from "./Starfish"; +import { TerritorialCrab } from "./TerritorialCrab"; +import { SeaTurtle } from "./SeaTurtle"; +import { Plankton } from "./Plankton"; +import { Dolphin } from "./Dolphin"; -export const UnderwaterDecorations: React.FC = () => { - // Randomly position a few jellyfish near the top half - const [jellyfish] = useState(() => - Array.from({ length: 3 }, (_, i) => ({ +interface UnderwaterDecorationsProps { + fishes: FishState[]; +} + +export const UnderwaterDecorations: React.FC = ({ fishes }) => { + // Randomly position jellyfish near the top half + const [jellyfish, setJellyfish] = useState(() => + Array.from({ length: 4 }, (_, i) => ({ id: i, x: Math.random() * window.innerWidth * 0.9, y: Math.random() * window.innerHeight * 0.5, size: 40 + Math.random() * 20, + isPlayful: false, })) ); - // Create several bubbles that start near the bottom and animate upward + // Simulate playful interactions every few seconds + useEffect(() => { + const interval = setInterval(() => { + setJellyfish((prev) => + prev.map((j) => ({ + ...j, + isPlayful: Math.random() < 0.3, // 30% chance to be playful + })) + ); + }, 3000); + return () => clearInterval(interval); + }, []); + + // Create several bubbles that start near the bottom const [bubbles] = useState(() => - Array.from({ length: 15 }, (_, i) => ({ + Array.from({ length: 20 }, (_, i) => ({ id: i, x: Math.random() * window.innerWidth, y: window.innerHeight - Math.random() * 100, @@ -28,9 +51,9 @@ export const UnderwaterDecorations: React.FC = () => { })) ); - // Place a few corals along the bottom + // Place corals along the bottom const [corals] = useState(() => - Array.from({ length: 5 }, (_, i) => ({ + Array.from({ length: 6 }, (_, i) => ({ id: i, x: Math.random() * (window.innerWidth - 80), y: window.innerHeight - 80, @@ -38,9 +61,9 @@ export const UnderwaterDecorations: React.FC = () => { })) ); - // And a few seashells at the bottom + // Seashells at the bottom const [seashells] = useState(() => - Array.from({ length: 3 }, (_, i) => ({ + Array.from({ length: 4 }, (_, i) => ({ id: i, x: Math.random() * (window.innerWidth - 60), y: window.innerHeight - 60, @@ -48,9 +71,9 @@ export const UnderwaterDecorations: React.FC = () => { })) ); - // Add some seaweed that gently sways + // Seaweed that gently sways const [seaweeds] = useState(() => - Array.from({ length: 4 }, (_, i) => ({ + Array.from({ length: 5 }, (_, i) => ({ id: i, x: Math.random() * (window.innerWidth - 80), y: window.innerHeight - 120, @@ -58,10 +81,76 @@ export const UnderwaterDecorations: React.FC = () => { })) ); + // Add starfish along the bottom + const [starfish] = useState(() => + Array.from({ length: 3 }, (_, i) => ({ + id: i, + x: Math.random() * (window.innerWidth - 50), + y: window.innerHeight - 150 + Math.random() * 50, + size: 30 + Math.random() * 10, + })) + ); + + // Add crabs that walk along the bottom + const [crabs] = useState(() => + Array.from({ length: 2 }, (_, i) => ({ + id: i, + x: Math.random() * (window.innerWidth - 60), + y: window.innerHeight - 70, + size: 25 + Math.random() * 10, + })) + ); + + // Add sea turtles in the middle area + const [seaTurtles] = useState(() => + Array.from({ length: 2 }, (_, i) => ({ + id: i, + x: Math.random() * (window.innerWidth - 100), + y: window.innerHeight * 0.3 + Math.random() * 50, + size: 50 + Math.random() * 20, + })) + ); + + // Add plankton particles + const [planktons] = useState(() => + Array.from({ length: 10 }, (_, i) => ({ + id: i, + x: Math.random() * window.innerWidth, + y: Math.random() * window.innerHeight, + size: 2 + Math.random() * 2, + duration: 4 + Math.random() * 4, + })) + ); + + // Add dolphins near the top/middle + const [dolphins] = useState(() => + Array.from({ length: 2 }, (_, i) => ({ + id: i, + x: Math.random() * (window.innerWidth * 0.7), + y: Math.random() * (window.innerHeight * 0.3), + size: 30 + Math.random() * 20, + })) + ); + return ( <> + {planktons.map((p) => ( + + ))} {jellyfish.map((j) => ( - + ))} {bubbles.map((b) => ( { {seaweeds.map((sw) => ( ))} + {starfish.map((s) => ( + + ))} + {crabs.map((c) => { + // Check if any fish are near this crab's territory + const hasNearbyFish = fishes.some( + fish => Math.hypot(fish.x - c.x, fish.y - c.y) < 50 + ); + return ( + + ); + })} + {seaTurtles.map((t) => ( + + ))} + {dolphins.map((d) => ( + + ))} ); }; diff --git a/showcase/fishies/src/types.ts b/showcase/fishies/src/types.ts new file mode 100644 index 0000000..1d42766 --- /dev/null +++ b/showcase/fishies/src/types.ts @@ -0,0 +1,16 @@ +export interface Position { + x: number; + y: number; +} + +export interface FishState extends Position { + id: number; + direction: number; + color: string; + speedX: number; + speedY: number; + isDying?: boolean; + dyingStartTime?: number; + isBeingEaten?: boolean; + isHiding?: boolean; +} From e8923a85fb66165561a2c4a310ebcfd1612095cb Mon Sep 17 00:00:00 2001 From: Brandon Chen Date: Thu, 6 Feb 2025 18:09:13 -0800 Subject: [PATCH 20/34] feat: initial minecraft-complex --- showcase/minecraft-complex/.eslintrc.cjs | 84 + showcase/minecraft-complex/.gitignore | 5 + showcase/minecraft-complex/README.md | 44 + .../minecraft-complex/app/entry.client.tsx | 18 + .../minecraft-complex/app/entry.server.tsx | 140 + showcase/minecraft-complex/app/root.tsx | 45 + .../minecraft-complex/app/routes/_index.tsx | 31 + .../app/routes/minecraft.tsx | 447 + showcase/minecraft-complex/app/tailwind.css | 12 + showcase/minecraft-complex/knowledge.md | 11 + showcase/minecraft-complex/package-lock.json | 11743 ++++++++++++++++ showcase/minecraft-complex/package.json | 46 + showcase/minecraft-complex/postcss.config.js | 6 + showcase/minecraft-complex/public/favicon.ico | Bin 0 -> 16958 bytes .../minecraft-complex/public/logo-dark.png | Bin 0 -> 80332 bytes .../minecraft-complex/public/logo-light.png | Bin 0 -> 5906 bytes .../public/textures/dirt.png | Bin 0 -> 353 bytes .../public/textures/grass.png | Bin 0 -> 281 bytes .../public/textures/stone.png | Bin 0 -> 276 bytes .../scripts/generate-textures.js | 94 + showcase/minecraft-complex/tailwind.config.ts | 22 + showcase/minecraft-complex/tsconfig.json | 32 + showcase/minecraft-complex/vite.config.ts | 24 + 23 files changed, 12804 insertions(+) create mode 100644 showcase/minecraft-complex/.eslintrc.cjs create mode 100644 showcase/minecraft-complex/.gitignore create mode 100644 showcase/minecraft-complex/README.md create mode 100644 showcase/minecraft-complex/app/entry.client.tsx create mode 100644 showcase/minecraft-complex/app/entry.server.tsx create mode 100644 showcase/minecraft-complex/app/root.tsx create mode 100644 showcase/minecraft-complex/app/routes/_index.tsx create mode 100644 showcase/minecraft-complex/app/routes/minecraft.tsx create mode 100644 showcase/minecraft-complex/app/tailwind.css create mode 100644 showcase/minecraft-complex/knowledge.md create mode 100644 showcase/minecraft-complex/package-lock.json create mode 100644 showcase/minecraft-complex/package.json create mode 100644 showcase/minecraft-complex/postcss.config.js create mode 100644 showcase/minecraft-complex/public/favicon.ico create mode 100644 showcase/minecraft-complex/public/logo-dark.png create mode 100644 showcase/minecraft-complex/public/logo-light.png create mode 100644 showcase/minecraft-complex/public/textures/dirt.png create mode 100644 showcase/minecraft-complex/public/textures/grass.png create mode 100644 showcase/minecraft-complex/public/textures/stone.png create mode 100644 showcase/minecraft-complex/scripts/generate-textures.js create mode 100644 showcase/minecraft-complex/tailwind.config.ts create mode 100644 showcase/minecraft-complex/tsconfig.json create mode 100644 showcase/minecraft-complex/vite.config.ts diff --git a/showcase/minecraft-complex/.eslintrc.cjs b/showcase/minecraft-complex/.eslintrc.cjs new file mode 100644 index 0000000..4f6f59e --- /dev/null +++ b/showcase/minecraft-complex/.eslintrc.cjs @@ -0,0 +1,84 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + ignorePatterns: ["!**/.server", "!**/.client"], + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + "import/resolver": { + typescript: {}, + }, + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.cjs"], + env: { + node: true, + }, + }, + ], +}; diff --git a/showcase/minecraft-complex/.gitignore b/showcase/minecraft-complex/.gitignore new file mode 100644 index 0000000..80ec311 --- /dev/null +++ b/showcase/minecraft-complex/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/.cache +/build +.env diff --git a/showcase/minecraft-complex/README.md b/showcase/minecraft-complex/README.md new file mode 100644 index 0000000..4519d13 --- /dev/null +++ b/showcase/minecraft-complex/README.md @@ -0,0 +1,44 @@ +# Remix Starter Template + +A minimal Remix starter template with TypeScript and Tailwind CSS. + +## Get this project + +Run the following to clone this starter template: + +```bash +codebuff --create remix my-app +``` + +## Quick Start + +```bash +npm run dev +``` + +Visit [http://localhost:3000](http://localhost:3000) + +## Development + +```bash +# Install dependencies +npm install + +# Start dev server +npm run dev + +# Type check +npm run typecheck + +# Lint +npm run lint + +# Build for production +npm run build +``` + +## Learn More + +- [Codebuff Docs](https://www.codebuff.com/docs) +- [Remix Docs](https://remix.run/docs) +- [Tailwind CSS](https://tailwindcss.com) diff --git a/showcase/minecraft-complex/app/entry.client.tsx b/showcase/minecraft-complex/app/entry.client.tsx new file mode 100644 index 0000000..94d5dc0 --- /dev/null +++ b/showcase/minecraft-complex/app/entry.client.tsx @@ -0,0 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + +import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; + +startTransition(() => { + hydrateRoot( + document, + + + + ); +}); diff --git a/showcase/minecraft-complex/app/entry.server.tsx b/showcase/minecraft-complex/app/entry.server.tsx new file mode 100644 index 0000000..45db322 --- /dev/null +++ b/showcase/minecraft-complex/app/entry.server.tsx @@ -0,0 +1,140 @@ +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.server + */ + +import { PassThrough } from "node:stream"; + +import type { AppLoadContext, EntryContext } from "@remix-run/node"; +import { createReadableStreamFromReadable } from "@remix-run/node"; +import { RemixServer } from "@remix-run/react"; +import { isbot } from "isbot"; +import { renderToPipeableStream } from "react-dom/server"; + +const ABORT_DELAY = 5_000; + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadContext: AppLoadContext +) { + return isbot(request.headers.get("user-agent") || "") + ? handleBotRequest( + request, + responseStatusCode, + responseHeaders, + remixContext + ) + : handleBrowserRequest( + request, + responseStatusCode, + responseHeaders, + remixContext + ); +} + +function handleBotRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onAllReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error); + } + }, + } + ); + + setTimeout(abort, ABORT_DELAY); + }); +} + +function handleBrowserRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onShellReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error); + } + }, + } + ); + + setTimeout(abort, ABORT_DELAY); + }); +} diff --git a/showcase/minecraft-complex/app/root.tsx b/showcase/minecraft-complex/app/root.tsx new file mode 100644 index 0000000..61c8b98 --- /dev/null +++ b/showcase/minecraft-complex/app/root.tsx @@ -0,0 +1,45 @@ +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, +} from "@remix-run/react"; +import type { LinksFunction } from "@remix-run/node"; + +import "./tailwind.css"; + +export const links: LinksFunction = () => [ + { rel: "preconnect", href: "https://fonts.googleapis.com" }, + { + rel: "preconnect", + href: "https://fonts.gstatic.com", + crossOrigin: "anonymous", + }, + { + rel: "stylesheet", + href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap", + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + + + {children} + + + + + ); +} + +export default function App() { + return ; +} diff --git a/showcase/minecraft-complex/app/routes/_index.tsx b/showcase/minecraft-complex/app/routes/_index.tsx new file mode 100644 index 0000000..5eb7785 --- /dev/null +++ b/showcase/minecraft-complex/app/routes/_index.tsx @@ -0,0 +1,31 @@ +import type { MetaFunction } from "@remix-run/node"; +import { Link } from "@remix-run/react"; + +export const meta: MetaFunction = () => { + return [ + { title: "New Remix App" }, + { name: "description", content: "Welcome to Remix!" }, + ]; +}; + +export default function Index() { + return ( +
+

Minecraft Clone

+
+

A simple Minecraft-like game where you can:

+
    +
  • Move around with WASD
  • +
  • Look around with the mouse
  • +
  • Mine blocks with left click
  • +
+
+ + Start Playing + +
+ ); +} diff --git a/showcase/minecraft-complex/app/routes/minecraft.tsx b/showcase/minecraft-complex/app/routes/minecraft.tsx new file mode 100644 index 0000000..633c76d --- /dev/null +++ b/showcase/minecraft-complex/app/routes/minecraft.tsx @@ -0,0 +1,447 @@ +import React, { useEffect, useRef } from "react"; +import * as THREE from "three"; +import { PointerLockControls } from "three/addons/controls/PointerLockControls.js"; + +export default function Minecraft() { + const mountRef = useRef(null); + + useEffect(() => { + if (!mountRef.current) return; + + const mount = mountRef.current; // Store ref value in variable for cleanup + + const scene = new THREE.Scene(); + scene.background = new THREE.Color(0x87ceeb); + scene.fog = new THREE.Fog(0x87ceeb, 50, 100); + + const camera = new THREE.PerspectiveCamera( + 75, + window.innerWidth / window.innerHeight, + 0.1, + 1000 + ); + camera.position.set(0, 20, 5); + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(window.innerWidth, window.innerHeight); + renderer.shadowMap.enabled = true; + mount.appendChild(renderer.domElement); + + const controls = new PointerLockControls(camera, renderer.domElement); + scene.add(controls.object); + + const moveState = { + forward: false, + backward: false, + left: false, + right: false, + jumping: false, + onGround: false, + velocity: new THREE.Vector3(), + direction: new THREE.Vector3(), + }; + const GRAVITY = 30.0; + const JUMP_FORCE = 12.0; + const MOVE_SPEED = 10.0; + + const inventory = { count: 0 }; + function updateInventoryUI() { + const invElement = document.getElementById("inventory"); + if (invElement) { + invElement.innerText = "Inventory: " + inventory.count; + } + } + + const onKeyDown = (event: KeyboardEvent) => { + switch (event.code) { + case "ArrowUp": + case "KeyW": + moveState.forward = true; + break; + case "ArrowDown": + case "KeyS": + moveState.backward = true; + break; + case "ArrowLeft": + case "KeyA": + moveState.left = true; + break; + case "ArrowRight": + case "KeyD": + moveState.right = true; + break; + case "Space": + if (moveState.onGround) { + moveState.velocity.y = JUMP_FORCE; + moveState.onGround = false; + } + break; + } + }; + + const onKeyUp = (event: KeyboardEvent) => { + switch (event.code) { + case "ArrowUp": + case "KeyW": + moveState.forward = false; + break; + case "ArrowDown": + case "KeyS": + moveState.backward = false; + break; + case "ArrowLeft": + case "KeyA": + moveState.left = false; + break; + case "ArrowRight": + case "KeyD": + moveState.right = false; + break; + } + }; + + mount.addEventListener("click", () => { + controls.lock(); + }); + + document.addEventListener("keydown", onKeyDown); + document.addEventListener("keyup", onKeyUp); + + const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); + scene.add(ambientLight); + + const sunLight = new THREE.DirectionalLight(0xffffff, 0.8); + sunLight.position.set(100, 100, 0); + sunLight.castShadow = true; + scene.add(sunLight); + + const blockSize = 1; + const textureLoader = new THREE.TextureLoader(); + + const grassTopTexture = textureLoader.load("/textures/grass.png"); + const grassSideTexture = textureLoader.load("/textures/dirt.png"); + const dirtTexture = textureLoader.load("/textures/dirt.png"); + const stoneTexture = textureLoader.load("/textures/stone.png"); + + [grassTopTexture, grassSideTexture, dirtTexture, stoneTexture].forEach( + (texture) => { + texture.magFilter = THREE.NearestFilter; + texture.minFilter = THREE.NearestFilter; + texture.repeat.set(1, 1); + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + } + ); + + const stoneMaterial = new THREE.MeshStandardMaterial({ + map: stoneTexture, + roughness: 1, + metalness: 0, + }); + + const dirtMaterial = new THREE.MeshStandardMaterial({ + map: dirtTexture, + roughness: 1, + metalness: 0, + }); + + const grassMaterials = [ + new THREE.MeshStandardMaterial({ map: grassSideTexture }), // right + new THREE.MeshStandardMaterial({ map: grassSideTexture }), // left + new THREE.MeshStandardMaterial({ map: grassTopTexture }), // top + new THREE.MeshStandardMaterial({ map: dirtTexture }), // bottom + new THREE.MeshStandardMaterial({ map: grassSideTexture }), // front + new THREE.MeshStandardMaterial({ map: grassSideTexture }), // back + ]; + + const blockGeo = new THREE.BoxGeometry(blockSize, blockSize, blockSize); + const blocks: THREE.Mesh[] = []; + + const gridSize = 32; + const maxHeight = 12; + + function noise(x: number, z: number) { + return ( + Math.sin(x * 0.3) * Math.cos(z * 0.2) * 2 + + Math.sin(x * 0.1 + z * 0.5) * 3 + + Math.cos((x + z) * 0.5) * 2 + ); + } + + for (let i = -Math.floor(gridSize / 2); i < Math.floor(gridSize / 2); i++) { + for ( + let j = -Math.floor(gridSize / 2); + j < Math.floor(gridSize / 2); + j++ + ) { + const height = Math.max(1, Math.floor(maxHeight / 2 + noise(i, j))); + + for (let y = 0; y < height; y++) { + let material; + if (y === height - 1) { + material = grassMaterials; + } else if (y >= height - 3) { + material = dirtMaterial; + } else { + material = stoneMaterial; + } + + const block = new THREE.Mesh(blockGeo, material); + block.position.set(i * blockSize, y, j * blockSize); + block.castShadow = true; + block.receiveShadow = true; + scene.add(block); + blocks.push(block); + } + } + } + + const raycaster = new THREE.Raycaster(); + const mouse = new THREE.Vector2(); + + let lastMineTime = 0; + const MINE_COOLDOWN = 250; + + function onMouseDown(event: MouseEvent) { + if (event.button !== 0) return; + + const currentTime = performance.now(); + if (currentTime - lastMineTime < MINE_COOLDOWN) return; + + mouse.set(0, 0); + raycaster.setFromCamera(mouse, camera); + const intersects = raycaster.intersectObjects(blocks); + if (intersects.length > 0) { + const hitBlock = intersects[0].object as THREE.Mesh; + scene.remove(hitBlock); + const index = blocks.indexOf(hitBlock); + if (index > -1) blocks.splice(index, 1); + inventory.count++; + updateInventoryUI(); + lastMineTime = currentTime; + } + } + window.addEventListener("mousedown", onMouseDown); + + function onRightMouseDown(event: MouseEvent) { + event.preventDefault(); + if (inventory.count <= 0) return; + + mouse.set(0, 0); + raycaster.setFromCamera(mouse, camera); + const intersects = raycaster.intersectObjects(blocks); + if (intersects.length > 0) { + const intersect = intersects[0]; + const normal = intersect.face?.normal; + if (!normal) return; + + const newBlockPos = new THREE.Vector3( + Math.round(intersect.point.x + normal.x * 0.5), + Math.round(intersect.point.y + normal.y * 0.5), + Math.round(intersect.point.z + normal.z * 0.5) + ); + + const exists = blocks.some( + (b) => + Math.abs(b.position.x - newBlockPos.x) < 0.1 && + Math.abs(b.position.y - newBlockPos.y) < 0.1 && + Math.abs(b.position.z - newBlockPos.z) < 0.1 + ); + + if (exists) return; + + const block = new THREE.Mesh(blockGeo, grassMaterials); + block.position.copy(newBlockPos); + block.castShadow = true; + block.receiveShadow = true; + scene.add(block); + blocks.push(block); + inventory.count--; + updateInventoryUI(); + } + } + window.addEventListener("contextmenu", onRightMouseDown); + + function onWindowResize() { + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + renderer.setSize(window.innerWidth, window.innerHeight); + } + window.addEventListener("resize", onWindowResize); + + let dayTime = 0; + const DAY_LENGTH = 600; + + function updateDayNightCycle(delta: number) { + dayTime = (dayTime + delta) % DAY_LENGTH; + const time = dayTime / DAY_LENGTH; + + const angle = time * Math.PI * 2; + sunLight.position.x = Math.cos(angle) * 100; + sunLight.position.y = Math.sin(angle) * 100; + + const skyColor = new THREE.Color(); + if (time < 0.25 || time > 0.75) { + skyColor.setRGB(0.1, 0.1, 0.3); + sunLight.intensity = 0.2; + ambientLight.intensity = 0.3; + } else { + skyColor.setRGB(0.529, 0.808, 0.922); + sunLight.intensity = 0.8; + ambientLight.intensity = 0.6; + } + scene.background = skyColor; + if (scene.fog) { + scene.fog.color = skyColor; + } + } + + function getTerrainHeight(x: number, z: number): number { + const i = Math.round(x); + const j = Math.round(z); + return Math.max(1, Math.floor(maxHeight / 2 + noise(i, j))); + } + + let prevTime = performance.now(); + function animate() { + const time = performance.now(); + const delta = (time - prevTime) / 1000; + + updateDayNightCycle(delta); + + moveState.velocity.y -= GRAVITY * delta; + const pos = controls.object.position; + + // Calculate potential new positions + const potentialX = pos.x + moveState.direction.x * MOVE_SPEED * delta; + const potentialZ = pos.z + moveState.direction.z * MOVE_SPEED * delta; + + // Get current and potential terrain heights + const currentHeight = getTerrainHeight(pos.x, pos.z); + const potentialHeightX = getTerrainHeight(potentialX, pos.z); + const potentialHeightZ = getTerrainHeight(pos.x, potentialZ); + + // Ground collision check + if (pos.y <= currentHeight + 1) { + moveState.velocity.y = 0; + pos.y = currentHeight + 1; + moveState.onGround = true; + } else { + moveState.onGround = false; + } + + // Update movement direction + moveState.direction.z = Number(moveState.forward) - Number(moveState.backward); + moveState.direction.x = Number(moveState.right) - Number(moveState.left); + moveState.direction.normalize(); + + // Block collision checks - only prevent movement if trying to move to higher terrain + if (potentialHeightX <= currentHeight) { + if (moveState.forward || moveState.backward) { + controls.moveForward(moveState.direction.z * MOVE_SPEED * delta); + } + } + if (potentialHeightZ <= currentHeight) { + if (moveState.left || moveState.right) { + controls.moveRight(moveState.direction.x * MOVE_SPEED * delta); + } + } + + // Apply gravity + controls.object.position.y += moveState.velocity.y * delta; + + renderer.render(scene, camera); + prevTime = time; + requestAnimationFrame(animate); + } + animate(); + + return () => { + mount.removeChild(renderer.domElement); + window.removeEventListener("mousedown", onMouseDown); + window.removeEventListener("contextmenu", onRightMouseDown); + window.removeEventListener("resize", onWindowResize); + document.removeEventListener("keydown", onKeyDown); + document.removeEventListener("keyup", onKeyUp); + }; + }, []); + + return ( + <> +
+
+ Inventory: 0 +
+
+
+
+
+
+
Click to start
+
WASD / Arrow Keys - Move
+
Space - Jump
+
Left Click - Mine
+
Right Click - Place Block
+
ESC - Pause
+
+ + ); +} diff --git a/showcase/minecraft-complex/app/tailwind.css b/showcase/minecraft-complex/app/tailwind.css new file mode 100644 index 0000000..303fe15 --- /dev/null +++ b/showcase/minecraft-complex/app/tailwind.css @@ -0,0 +1,12 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html, +body { + @apply bg-white dark:bg-gray-950; + + @media (prefers-color-scheme: dark) { + color-scheme: dark; + } +} diff --git a/showcase/minecraft-complex/knowledge.md b/showcase/minecraft-complex/knowledge.md new file mode 100644 index 0000000..892e8f5 --- /dev/null +++ b/showcase/minecraft-complex/knowledge.md @@ -0,0 +1,11 @@ +# Remix Template Knowledge + +## Project Overview +A minimal Remix + TypeScript starter template with Tailwind CSS for styling. + +## Verifying changes +After every change, run: +```bash +npm run typecheck && npm run lint +``` +This will check for type errors and lint issues. diff --git a/showcase/minecraft-complex/package-lock.json b/showcase/minecraft-complex/package-lock.json new file mode 100644 index 0000000..2e0fe88 --- /dev/null +++ b/showcase/minecraft-complex/package-lock.json @@ -0,0 +1,11743 @@ +{ + "name": "remix", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "remix", + "dependencies": { + "@remix-run/node": "^2.15.2", + "@remix-run/react": "^2.15.2", + "@remix-run/serve": "^2.15.2", + "@types/three": "^0.173.0", + "canvas": "^3.1.0", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "three": "^0.173.0" + }, + "devDependencies": { + "@remix-run/dev": "^2.15.2", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "autoprefixer": "^10.4.19", + "eslint": "^8.38.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "postcss": "^8.4.38", + "tailwindcss": "^3.4.4", + "typescript": "~5.3.3", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", + "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.7", + "@babel/parser": "^7.26.7", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.26.7", + "@babel/types": "^7.26.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz", + "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", + "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.26.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", + "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.7.tgz", + "integrity": "sha512-5cJurntg+AT+cgelGP9Bt788DKiAw9gIMSMU2NJrLAilnj0m8WZWUNZPSLOmadYsujHutpgElO+50foX+ib/Wg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", + "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.7", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", + "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "dev": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.6.tgz", + "integrity": "sha512-bSC9YVUjADDy1gae8RrioINU6e1lCkg3VGVwm0QQ2E1CWcC4gnMce9+B6RpxuSsrsXsk1yojn7sp1fnG8erE2g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.6.tgz", + "integrity": "sha512-YnYSCceN/dUzUr5kdtUzB+wZprCafuD89Hs0Aqv9QSdwhYQybhXTaSTcrl6X/aWThn1a/j0eEpUBGOE7269REg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.6.tgz", + "integrity": "sha512-MVcYcgSO7pfu/x34uX9u2QIZHmXAB7dEiLQC5bBl5Ryqtpj9lT2sg3gNDEsrPEmimSJW2FXIaxqSQ501YLDsZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.6.tgz", + "integrity": "sha512-bsDRvlbKMQMt6Wl08nHtFz++yoZHsyTOxnjfB2Q95gato+Yi4WnRl13oC2/PJJA9yLCoRv9gqT/EYX0/zDsyMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.6.tgz", + "integrity": "sha512-xh2A5oPrYRfMFz74QXIQTQo8uA+hYzGWJFoeTE8EvoZGHb+idyV4ATaukaUvnnxJiauhs/fPx3vYhU4wiGfosg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.6.tgz", + "integrity": "sha512-EnUwjRc1inT4ccZh4pB3v1cIhohE2S4YXlt1OvI7sw/+pD+dIE4smwekZlEPIwY6PhU6oDWwITrQQm5S2/iZgg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.6.tgz", + "integrity": "sha512-Uh3HLWGzH6FwpviUcLMKPCbZUAFzv67Wj5MTwK6jn89b576SR2IbEp+tqUHTr8DIl0iDmBAf51MVaP7pw6PY5Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.6.tgz", + "integrity": "sha512-7YdGiurNt7lqO0Bf/U9/arrPWPqdPqcV6JCZda4LZgEn+PTQ5SMEI4MGR52Bfn3+d6bNEGcWFzlIxiQdS48YUw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.6.tgz", + "integrity": "sha512-bUR58IFOMJX523aDVozswnlp5yry7+0cRLCXDsxnUeQYJik1DukMY+apBsLOZJblpH+K7ox7YrKrHmJoWqVR9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.6.tgz", + "integrity": "sha512-ujp8uoQCM9FRcbDfkqECoARsLnLfCUhKARTP56TFPog8ie9JG83D5GVKjQ6yVrEVdMie1djH86fm98eY3quQkQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.6.tgz", + "integrity": "sha512-y2NX1+X/Nt+izj9bLoiaYB9YXT/LoaQFYvCkVD77G/4F+/yuVXYCWz4SE9yr5CBMbOxOfBcy/xFL4LlOeNlzYQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.6.tgz", + "integrity": "sha512-09AXKB1HDOzXD+j3FdXCiL/MWmZP0Ex9eR8DLMBVcHorrWJxWmY8Nms2Nm41iRM64WVx7bA/JVHMv081iP2kUA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.6.tgz", + "integrity": "sha512-AmLhMzkM8JuqTIOhxnX4ubh0XWJIznEynRnZAVdA2mMKE6FAfwT2TWKTwdqMG+qEaeyDPtfNoZRpJbD4ZBv0Tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.6.tgz", + "integrity": "sha512-Y4Ri62PfavhLQhFbqucysHOmRamlTVK10zPWlqjNbj2XMea+BOs4w6ASKwQwAiqf9ZqcY9Ab7NOU4wIgpxwoSQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.6.tgz", + "integrity": "sha512-SPUiz4fDbnNEm3JSdUW8pBJ/vkop3M1YwZAVwvdwlFLoJwKEZ9L98l3tzeyMzq27CyepDQ3Qgoba44StgbiN5Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.6.tgz", + "integrity": "sha512-a3yHLmOodHrzuNgdpB7peFGPx1iJ2x6m+uDvhP2CKdr2CwOaqEFMeSqYAHU7hG+RjCq8r2NFujcd/YsEsFgTGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.6.tgz", + "integrity": "sha512-EanJqcU/4uZIBreTrnbnre2DXgXSa+Gjap7ifRfllpmyAU7YMvaXmljdArptTHmjrkkKm9BK6GH5D5Yo+p6y5A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.6.tgz", + "integrity": "sha512-xaxeSunhQRsTNGFanoOkkLtnmMn5QbA0qBhNet/XLVsc+OVkpIWPHcr3zTW2gxVU5YOHFbIHR9ODuaUdNza2Vw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.6.tgz", + "integrity": "sha512-gnMnMPg5pfMkZvhHee21KbKdc6W3GR8/JuE0Da1kjwpK6oiFU3nqfHuVPgUX2rsOx9N2SadSQTIYV1CIjYG+xw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.6.tgz", + "integrity": "sha512-G95n7vP1UnGJPsVdKXllAJPtqjMvFYbN20e8RK8LVLhlTiSOH1sd7+Gt7rm70xiG+I5tM58nYgwWrLs6I1jHqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.6.tgz", + "integrity": "sha512-96yEFzLhq5bv9jJo5JhTs1gI+1cKQ83cUpyxHuGqXVwQtY5Eq54ZEsKs8veKtiKwlrNimtckHEkj4mRh4pPjsg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.6.tgz", + "integrity": "sha512-n6d8MOyUrNp6G4VSpRcgjs5xj4A91svJSaiwLIDWVWEsZtpN5FA9NlBbZHDmAJc2e8e6SF4tkBD3HAvPF+7igA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jspm/core": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@jspm/core/-/core-2.0.1.tgz", + "integrity": "sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==", + "dev": true + }, + "node_modules/@mdx-js/mdx": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz", + "integrity": "sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/mdx": "^2.0.0", + "estree-util-build-jsx": "^2.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "estree-util-to-js": "^1.1.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^2.0.0", + "markdown-extensions": "^1.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^2.0.0", + "remark-parse": "^10.0.0", + "remark-rehype": "^10.0.0", + "unified": "^10.0.0", + "unist-util-position-from-estree": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q==", + "dev": true, + "dependencies": { + "@npmcli/git": "^4.1.0", + "glob": "^10.2.2", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@remix-run/dev": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.15.2.tgz", + "integrity": "sha512-o8lix8t4GBhtXjo/G1IzwtHVW5GRMs7amtFtBHiR1bhSyK7VyX5qGtTDmJyny5QDv83pxaLOCiE0dUng2BCoyQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.8", + "@babel/generator": "^7.21.5", + "@babel/parser": "^7.21.8", + "@babel/plugin-syntax-decorators": "^7.22.10", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/preset-typescript": "^7.21.5", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.22.5", + "@mdx-js/mdx": "^2.3.0", + "@npmcli/package-json": "^4.0.1", + "@remix-run/node": "2.15.2", + "@remix-run/router": "1.21.0", + "@remix-run/server-runtime": "2.15.2", + "@types/mdx": "^2.0.5", + "@vanilla-extract/integration": "^6.2.0", + "arg": "^5.0.1", + "cacache": "^17.1.3", + "chalk": "^4.1.2", + "chokidar": "^3.5.1", + "cross-spawn": "^7.0.3", + "dotenv": "^16.0.0", + "es-module-lexer": "^1.3.1", + "esbuild": "0.17.6", + "esbuild-plugins-node-modules-polyfill": "^1.6.0", + "execa": "5.1.1", + "exit-hook": "2.2.1", + "express": "^4.20.0", + "fs-extra": "^10.0.0", + "get-port": "^5.1.1", + "gunzip-maybe": "^1.4.2", + "jsesc": "3.0.2", + "json5": "^2.2.2", + "lodash": "^4.17.21", + "lodash.debounce": "^4.0.8", + "minimatch": "^9.0.0", + "ora": "^5.4.1", + "picocolors": "^1.0.0", + "picomatch": "^2.3.1", + "pidtree": "^0.6.0", + "postcss": "^8.4.19", + "postcss-discard-duplicates": "^5.1.0", + "postcss-load-config": "^4.0.1", + "postcss-modules": "^6.0.0", + "prettier": "^2.7.1", + "pretty-ms": "^7.0.1", + "react-refresh": "^0.14.0", + "remark-frontmatter": "4.0.1", + "remark-mdx-frontmatter": "^1.0.1", + "semver": "^7.3.7", + "set-cookie-parser": "^2.6.0", + "tar-fs": "^2.1.1", + "tsconfig-paths": "^4.0.0", + "valibot": "^0.41.0", + "vite-node": "^1.6.0", + "ws": "^7.5.10" + }, + "bin": { + "remix": "dist/cli.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@remix-run/react": "^2.15.2", + "@remix-run/serve": "^2.15.2", + "typescript": "^5.1.0", + "vite": "^5.1.0", + "wrangler": "^3.28.2" + }, + "peerDependenciesMeta": { + "@remix-run/serve": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vite": { + "optional": true + }, + "wrangler": { + "optional": true + } + } + }, + "node_modules/@remix-run/express": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-2.15.2.tgz", + "integrity": "sha512-54FKQ6/Zj2DCxc4/9tWKUJLPkFakCUf1m7j7a5zp4JGDr436lkZEpS9btfoBZAVq14SIMp5Uc4yt5rUJ1PMORw==", + "dependencies": { + "@remix-run/node": "2.15.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "express": "^4.20.0", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@remix-run/node": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.15.2.tgz", + "integrity": "sha512-NS/h5uxje7DYCNgcKqKAiUhf0r2HVnoYUBWLyIIMmCUP1ddWurBP6xTPcWzGhEvV/EvguniYi1wJZ5+X8sonWw==", + "dependencies": { + "@remix-run/server-runtime": "2.15.2", + "@remix-run/web-fetch": "^4.4.2", + "@web3-storage/multipart-parser": "^1.0.0", + "cookie-signature": "^1.1.0", + "source-map-support": "^0.5.21", + "stream-slice": "^0.1.2", + "undici": "^6.11.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@remix-run/react": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.15.2.tgz", + "integrity": "sha512-NAAMsSgoC/sdOgovUewwRCE/RUm3F+MBxxZKfwu3POCNeHaplY5qGkH/y8PUXvdN1EBG7Z0Ko43dyzCfcEy5PA==", + "dependencies": { + "@remix-run/router": "1.21.0", + "@remix-run/server-runtime": "2.15.2", + "react-router": "6.28.1", + "react-router-dom": "6.28.1", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@remix-run/router": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", + "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@remix-run/serve": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/serve/-/serve-2.15.2.tgz", + "integrity": "sha512-m/nZtAUzzGcixNgNc3RNjA1ocFlWAuZFALpZ5fJdPXmITwqRwfjo/1gI+jx7AL7haoo+4j/sAljuAQw2CiswXA==", + "dependencies": { + "@remix-run/express": "2.15.2", + "@remix-run/node": "2.15.2", + "chokidar": "^3.5.3", + "compression": "^1.7.4", + "express": "^4.20.0", + "get-port": "5.1.1", + "morgan": "^1.10.0", + "source-map-support": "^0.5.21" + }, + "bin": { + "remix-serve": "dist/cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@remix-run/server-runtime": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.15.2.tgz", + "integrity": "sha512-OqiPcvEnnU88B8b1LIWHHkQ3Tz2GDAmQ1RihFNQsbrFKpDsQLkw0lJlnfgKA/uHd0CEEacpfV7C9qqJT3V6Z2g==", + "dependencies": { + "@remix-run/router": "1.21.0", + "@types/cookie": "^0.6.0", + "@web3-storage/multipart-parser": "^1.0.0", + "cookie": "^0.6.0", + "set-cookie-parser": "^2.4.8", + "source-map": "^0.7.3", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@remix-run/web-blob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-blob/-/web-blob-3.1.0.tgz", + "integrity": "sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==", + "dependencies": { + "@remix-run/web-stream": "^1.1.0", + "web-encoding": "1.1.5" + } + }, + "node_modules/@remix-run/web-fetch": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.4.2.tgz", + "integrity": "sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==", + "dependencies": { + "@remix-run/web-blob": "^3.1.0", + "@remix-run/web-file": "^3.1.0", + "@remix-run/web-form-data": "^3.1.0", + "@remix-run/web-stream": "^1.1.0", + "@web3-storage/multipart-parser": "^1.0.0", + "abort-controller": "^3.0.0", + "data-uri-to-buffer": "^3.0.1", + "mrmime": "^1.0.0" + }, + "engines": { + "node": "^10.17 || >=12.3" + } + }, + "node_modules/@remix-run/web-file": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-file/-/web-file-3.1.0.tgz", + "integrity": "sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==", + "dependencies": { + "@remix-run/web-blob": "^3.1.0" + } + }, + "node_modules/@remix-run/web-form-data": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-form-data/-/web-form-data-3.1.0.tgz", + "integrity": "sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==", + "dependencies": { + "web-encoding": "1.1.5" + } + }, + "node_modules/@remix-run/web-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-stream/-/web-stream-1.1.0.tgz", + "integrity": "sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==", + "dependencies": { + "web-streams-polyfill": "^3.1.1" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.0.tgz", + "integrity": "sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.0.tgz", + "integrity": "sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.0.tgz", + "integrity": "sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.0.tgz", + "integrity": "sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.0.tgz", + "integrity": "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.0.tgz", + "integrity": "sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.0.tgz", + "integrity": "sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.0.tgz", + "integrity": "sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.0.tgz", + "integrity": "sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.0.tgz", + "integrity": "sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.0.tgz", + "integrity": "sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.0.tgz", + "integrity": "sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.0.tgz", + "integrity": "sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.0.tgz", + "integrity": "sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.0.tgz", + "integrity": "sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.0.tgz", + "integrity": "sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.0.tgz", + "integrity": "sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.0.tgz", + "integrity": "sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.0.tgz", + "integrity": "sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "license": "MIT" + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "dev": true, + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "dev": true, + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.10.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz", + "integrity": "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==", + "dev": true, + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", + "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "dev": true, + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@types/stats.js": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", + "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==", + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.173.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.173.0.tgz", + "integrity": "sha512-KtNjfI/CRB6JVKIVeZM1R3GYDX2wkoV2itNcQu2j4d7qkhjGOuB+s2oF6jl9mztycDLGMtrAnJQYxInC8Bb20A==", + "license": "MIT", + "dependencies": { + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": "*", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~0.18.1" + } + }, + "node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true + }, + "node_modules/@types/webxr": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.21.tgz", + "integrity": "sha512-geZIAtLzjGmgY2JUi6VxXdCrTb99A7yP49lxLr2Nm/uIK0PkkxcEi4OGhoGDO4pxCf3JwGz2GiJL2Ej4K2bKaA==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true + }, + "node_modules/@vanilla-extract/babel-plugin-debug-ids": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vanilla-extract/babel-plugin-debug-ids/-/babel-plugin-debug-ids-1.2.0.tgz", + "integrity": "sha512-z5nx2QBnOhvmlmBKeRX5sPVLz437wV30u+GJL+Hzj1rGiJYVNvgIIlzUpRNjVQ0MgAgiQIqIUbqPnmMc6HmDlQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9" + } + }, + "node_modules/@vanilla-extract/css": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.17.0.tgz", + "integrity": "sha512-W6FqVFDD+C71ZlKsuj0MxOXSvHb1tvQ9h/+79aYfi097wLsALrnnBzd0by8C///iurrpQ3S+SH74lXd7Lr9MvA==", + "dev": true, + "dependencies": { + "@emotion/hash": "^0.9.0", + "@vanilla-extract/private": "^1.0.6", + "css-what": "^6.1.0", + "cssesc": "^3.0.0", + "csstype": "^3.0.7", + "dedent": "^1.5.3", + "deep-object-diff": "^1.1.9", + "deepmerge": "^4.2.2", + "lru-cache": "^10.4.3", + "media-query-parser": "^2.0.2", + "modern-ahocorasick": "^1.0.0", + "picocolors": "^1.0.0" + } + }, + "node_modules/@vanilla-extract/css/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/@vanilla-extract/integration": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@vanilla-extract/integration/-/integration-6.5.0.tgz", + "integrity": "sha512-E2YcfO8vA+vs+ua+gpvy1HRqvgWbI+MTlUpxA8FvatOvybuNcWAY0CKwQ/Gpj7rswYKtC6C7+xw33emM6/ImdQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.20.7", + "@babel/plugin-syntax-typescript": "^7.20.0", + "@vanilla-extract/babel-plugin-debug-ids": "^1.0.4", + "@vanilla-extract/css": "^1.14.0", + "esbuild": "npm:esbuild@~0.17.6 || ~0.18.0 || ~0.19.0", + "eval": "0.1.8", + "find-up": "^5.0.0", + "javascript-stringify": "^2.0.1", + "lodash": "^4.17.21", + "mlly": "^1.4.2", + "outdent": "^0.8.0", + "vite": "^5.0.11", + "vite-node": "^1.2.0" + } + }, + "node_modules/@vanilla-extract/private": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@vanilla-extract/private/-/private-1.0.6.tgz", + "integrity": "sha512-ytsG/JLweEjw7DBuZ/0JCN4WAQgM9erfSTdS1NQY778hFQSZ6cfCDEZZ0sgVm4k54uNz6ImKB33AYvSR//fjxw==", + "dev": true + }, + "node_modules/@web3-storage/multipart-parser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz", + "integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==" + }, + "node_modules/@webgpu/types": { + "version": "0.1.54", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.54.tgz", + "integrity": "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg==", + "license": "BSD-3-Clause" + }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "dev": true, + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "dependencies": { + "pako": "~0.2.0" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001695", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", + "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/canvas": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-3.1.0.tgz", + "integrity": "sha512-tTj3CqqukVJ9NgSahykNwtGda7V33VLObwrHfzT0vqJXu7J4d4C/7kQQW3fOEGDfZZoILPut5H00gOjyttPGyg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "^18.12.0 || >= 20.9.0" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dev": true, + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deep-object-diff": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz", + "integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.88", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.88.tgz", + "integrity": "sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", + "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.6.tgz", + "integrity": "sha512-TKFRp9TxrJDdRWfSsSERKEovm6v30iHnrjlcGhLBOtReE28Yp1VSBRfO3GTaOFMoxsNerx4TjrhzSuma9ha83Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.6", + "@esbuild/android-arm64": "0.17.6", + "@esbuild/android-x64": "0.17.6", + "@esbuild/darwin-arm64": "0.17.6", + "@esbuild/darwin-x64": "0.17.6", + "@esbuild/freebsd-arm64": "0.17.6", + "@esbuild/freebsd-x64": "0.17.6", + "@esbuild/linux-arm": "0.17.6", + "@esbuild/linux-arm64": "0.17.6", + "@esbuild/linux-ia32": "0.17.6", + "@esbuild/linux-loong64": "0.17.6", + "@esbuild/linux-mips64el": "0.17.6", + "@esbuild/linux-ppc64": "0.17.6", + "@esbuild/linux-riscv64": "0.17.6", + "@esbuild/linux-s390x": "0.17.6", + "@esbuild/linux-x64": "0.17.6", + "@esbuild/netbsd-x64": "0.17.6", + "@esbuild/openbsd-x64": "0.17.6", + "@esbuild/sunos-x64": "0.17.6", + "@esbuild/win32-arm64": "0.17.6", + "@esbuild/win32-ia32": "0.17.6", + "@esbuild/win32-x64": "0.17.6" + } + }, + "node_modules/esbuild-plugins-node-modules-polyfill": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/esbuild-plugins-node-modules-polyfill/-/esbuild-plugins-node-modules-polyfill-1.6.8.tgz", + "integrity": "sha512-bRB4qbgUDWrdY1eMk123KiaCSW9VzQ+QLZrmU7D//cCFkmksPd9mUMpmWoFK/rxjIeTfTSOpKCoGoimlvI+AWw==", + "dev": true, + "dependencies": { + "@jspm/core": "2.0.1", + "local-pkg": "^0.5.0", + "resolve.exports": "^2.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.14.0 <=0.24.x" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", + "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", + "dev": true, + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.7", + "enhanced-resolve": "^5.15.0", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3", + "stable-hash": "^0.0.4" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz", + "integrity": "sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz", + "integrity": "sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz", + "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz", + "integrity": "sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz", + "integrity": "sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==", + "dev": true, + "dependencies": { + "is-plain-obj": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/estree-util-visit": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz", + "integrity": "sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "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", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dev": true, + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz", + "integrity": "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, + "dependencies": { + "loader-utils": "^3.2.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-to-estree": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", + "integrity": "sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "estree-util-attach-comments": "^2.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "hast-util-whitespace": "^2.0.0", + "mdast-util-mdx-expression": "^1.0.0", + "mdast-util-mdxjs-esm": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.1", + "unist-util-position": "^4.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hosted-git-info": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", + "integrity": "sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/is-bun-module": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", + "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "dev": true, + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.6" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isbot": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/isbot/-/isbot-4.4.0.tgz", + "integrity": "sha512-8ZvOWUA68kyJO4hHJdWjyreq7TYNWTS9y15IzeqVdKxR9pPr3P/3r9AHcoIv9M0Rllkao5qWz2v1lmcyKIVCzQ==", + "engines": { + "node": ">=18" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "dev": true + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "dev": true, + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-extensions": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", + "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-definitions": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", + "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", + "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "mdast-util-to-string": "^3.1.0", + "micromark": "^3.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-decode-string": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.1.tgz", + "integrity": "sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0", + "micromark-extension-frontmatter": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz", + "integrity": "sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==", + "dev": true, + "dependencies": { + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-mdx-expression": "^1.0.0", + "mdast-util-mdx-jsx": "^2.0.0", + "mdast-util-mdxjs-esm": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz", + "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz", + "integrity": "sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "ccount": "^2.0.0", + "mdast-util-from-markdown": "^1.1.0", + "mdast-util-to-markdown": "^1.3.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz", + "integrity": "sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", + "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", + "dev": true, + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-definitions": "^5.0.0", + "micromark-util-sanitize-uri": "^1.1.0", + "trim-lines": "^3.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", + "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "micromark-util-decode-string": "^1.0.0", + "unist-util-visit": "^4.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/media-query-parser": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/media-query-parser/-/media-query-parser-2.0.2.tgz", + "integrity": "sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/meshoptimizer": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", + "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "micromark-core-commonmark": "^1.0.1", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-frontmatter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.1.1.tgz", + "integrity": "sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ==", + "dev": true, + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz", + "integrity": "sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-factory-mdx-expression": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz", + "integrity": "sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==", + "dev": true, + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "micromark-factory-mdx-expression": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz", + "integrity": "sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==", + "dev": true, + "dependencies": { + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz", + "integrity": "sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==", + "dev": true, + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^1.0.0", + "micromark-extension-mdx-jsx": "^1.0.0", + "micromark-extension-mdx-md": "^1.0.0", + "micromark-extension-mdxjs-esm": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz", + "integrity": "sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-core-commonmark": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-position-from-estree": "^1.1.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz", + "integrity": "sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-position-from-estree": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", + "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", + "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz", + "integrity": "sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^2.0.0", + "estree-util-visit": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "dev": true, + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, + "node_modules/modern-ahocorasick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modern-ahocorasick/-/modern-ahocorasick-1.1.0.tgz", + "integrity": "sha512-sEKPVl2rM+MNVkGQt3ChdmD8YsigmXdn5NifZn6jiwn9LRJpWm8F3guhaqrJT/JOat6pwpbXEk6kv+b9DMIjsQ==", + "dev": true + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.74.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz", + "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", + "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", + "dev": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/outdent": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz", + "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==", + "dev": true + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", + "dev": true + }, + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-modules": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.1.tgz", + "integrity": "sha512-zyo2sAkVvuZFFy0gc2+4O+xar5dYlaVy/ebO24KT0ftk/iJevSNyPyQellsBLlnccwh7f6V6Y4GvuKRYToNgpQ==", + "dev": true, + "dependencies": { + "generic-names": "^4.0.0", + "icss-utils": "^5.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.3" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nested/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prebuild-install/node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-ms": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", + "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", + "dev": true, + "dependencies": { + "parse-ms": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.28.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.1.tgz", + "integrity": "sha512-2omQTA3rkMljmrvvo6WtewGdVh45SpL9hGiCI9uUrwGGfNFDIvGK4gYJsKlJoNVi6AQZcopSCballL+QGOm7fA==", + "dependencies": { + "@remix-run/router": "1.21.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.28.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.1.tgz", + "integrity": "sha512-YraE27C/RdjcZwl5UCqF/ffXnZDxpJdk9Q6jw38SZHjXs7NNdpViq2l2c7fO7+4uWaEfcwfGCv3RSg4e1By/fQ==", + "dependencies": { + "@remix-run/router": "1.21.0", + "react-router": "6.28.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/remark-frontmatter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz", + "integrity": "sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-frontmatter": "^1.0.0", + "micromark-extension-frontmatter": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz", + "integrity": "sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==", + "dev": true, + "dependencies": { + "mdast-util-mdx": "^2.0.0", + "micromark-extension-mdxjs": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx-frontmatter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx-frontmatter/-/remark-mdx-frontmatter-1.1.1.tgz", + "integrity": "sha512-7teX9DW4tI2WZkXS4DBxneYSY7NHiXl4AKdWDO9LXVweULlCT8OPWsOjLEnMIXViN1j+QcY8mfbq3k0EK6x3uA==", + "dev": true, + "dependencies": { + "estree-util-is-identifier-name": "^1.0.0", + "estree-util-value-to-estree": "^1.0.0", + "js-yaml": "^4.0.0", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=12.2.0" + } + }, + "node_modules/remark-mdx-frontmatter/node_modules/estree-util-is-identifier-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-1.1.0.tgz", + "integrity": "sha512-OVJZ3fGGt9By77Ix9NhaRbzfbDV/2rx9EP7YIDJTmsZSEc5kYn2vWcNccYyahJL2uAQZK2a5Or2i0wtIKTPoRQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-parse": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", + "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz", + "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==", + "dev": true, + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-to-hast": "^12.1.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/rollup": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.0.tgz", + "integrity": "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.32.0", + "@rollup/rollup-android-arm64": "4.32.0", + "@rollup/rollup-darwin-arm64": "4.32.0", + "@rollup/rollup-darwin-x64": "4.32.0", + "@rollup/rollup-freebsd-arm64": "4.32.0", + "@rollup/rollup-freebsd-x64": "4.32.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.32.0", + "@rollup/rollup-linux-arm-musleabihf": "4.32.0", + "@rollup/rollup-linux-arm64-gnu": "4.32.0", + "@rollup/rollup-linux-arm64-musl": "4.32.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.32.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0", + "@rollup/rollup-linux-riscv64-gnu": "4.32.0", + "@rollup/rollup-linux-s390x-gnu": "4.32.0", + "@rollup/rollup-linux-x64-gnu": "4.32.0", + "@rollup/rollup-linux-x64-musl": "4.32.0", + "@rollup/rollup-win32-arm64-msvc": "4.32.0", + "@rollup/rollup-win32-ia32-msvc": "4.32.0", + "@rollup/rollup-win32-x64-msvc": "4.32.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", + "dev": true + }, + "node_modules/ssri": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/stable-hash": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", + "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true + }, + "node_modules/stream-slice": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", + "integrity": "sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "dev": true, + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", + "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/tar-fs/node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/three": { + "version": "0.173.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.173.0.tgz", + "integrity": "sha512-AUwVmViIEUgBwxJJ7stnF0NkPpZxx1aZ6WiAbQ/Qq61h6I9UR4grXtZDmO8mnlaNORhHnIBlXJ1uBxILEKuVyw==", + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "dev": true + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/tsconfck": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.4.tgz", + "integrity": "sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==", + "dev": true, + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "6.21.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", + "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true + }, + "node_modules/unified": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", + "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "bail": "^2.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz", + "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz", + "integrity": "sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uvu": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "dev": true, + "dependencies": { + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" + }, + "bin": { + "uvu": "bin.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/valibot": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.41.0.tgz", + "integrity": "sha512-igDBb8CTYr8YTQlOKgaN9nSS0Be7z+WRuaeYqGf3Cjz3aKmSnqEmYnkfVjzIuumGqfHpa3fLIvMEAfhrpqN8ng==", + "dev": true, + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.14", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz", + "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/vite-tsconfig-paths": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz", + "integrity": "sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/showcase/minecraft-complex/package.json b/showcase/minecraft-complex/package.json new file mode 100644 index 0000000..53834b3 --- /dev/null +++ b/showcase/minecraft-complex/package.json @@ -0,0 +1,46 @@ +{ + "name": "remix", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "build": "remix vite:build", + "dev": "remix vite:dev", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", + "start": "remix-serve ./build/server/index.js", + "typecheck": "tsc" + }, + "dependencies": { + "@remix-run/node": "^2.15.2", + "@remix-run/react": "^2.15.2", + "@remix-run/serve": "^2.15.2", + "@types/three": "^0.173.0", + "canvas": "^3.1.0", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "three": "^0.173.0" + }, + "devDependencies": { + "@remix-run/dev": "^2.15.2", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "autoprefixer": "^10.4.19", + "eslint": "^8.38.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "postcss": "^8.4.38", + "tailwindcss": "^3.4.4", + "typescript": "~5.3.3", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/showcase/minecraft-complex/postcss.config.js b/showcase/minecraft-complex/postcss.config.js new file mode 100644 index 0000000..2aa7205 --- /dev/null +++ b/showcase/minecraft-complex/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/showcase/minecraft-complex/public/favicon.ico b/showcase/minecraft-complex/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8830cf6821b354114848e6354889b8ecf6d2bc61 GIT binary patch literal 16958 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 EKbET!0{{R3 literal 0 HcmV?d00001 diff --git a/showcase/minecraft-complex/public/logo-dark.png b/showcase/minecraft-complex/public/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..b24c7aee3a86dad7eb334ba6fba94e5b18b84215 GIT binary patch literal 80332 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 BAPKNXC&B9%2=3YBbo!Y+L4D-GS zx+<%yIkO%e%ds?J1tiR$$gCYDEV2}T05KaP78&fp;z3}Gl~upP8iDOg52{DM>#Ni| ze)hjm-~JE&p!$7J?Ndi^SLXmHbGT=7;M?Z_a5H!UU0AMN+_N@rSj(2G1)e@_#83jP zO7I$iPE1HUGVRw26EFkdxCou8!4})0{#$lE1mrw@Xj}2P0EL80DI|JDv|`qn^LzO| z_S!>j<0QdsXW)PzxAW(x4!U|+*||fSHNpm2Y)09tF>zrUl`(LaSz{6d5VJr;fEcrv zLcVyt>q@e(@EewZ$@Ib|0TC z4k^7@;)Y8A(p&;rbYW#NH_HO}D3Ud0zF+5>^gZRD2XM7-DSc#9v22>Ugel(Ty1(Oh ztvq)N1)QlcUjSy#rD~TOgGRIiX9!q@ zq)STUV+c8`BM^>0)n%KB9rCgt_4Tk|ru}{Ly{lItKW|@F`&ag>ZlkMv=X#-<^j`4Q zuC$3oHl`NYPLDZUfEd$K4OhcxoNXz+iq{SN*;!a(5V{fIiV1gf_;#qfa48hCc2q_H zOp*kvy(aA|A5%~M$hWCK`ZvE(y<>k@En%w9dJ-wL$e<$>N_80NY2e5%wQ871rSvyO zT$=~_5&pC!9x*;x8B)8HsF235(T7*S4cg!h(7241QilN7WPxJsWhSnRSV~n}oSCYM~bEP#FYiBG&`YSl;Oa;6(mDNM7 zqbM?VJ~p$8Nndefep@qvL3$_+*E`NxMao~2O?b0o%86RC;A4>~BMe4$2Tvz!E9UlmY93s|lIKUV~nw zm0<+~_OU1+a|(hy68J&!Bu?SXE}}8}NKqLW!3%_3w_?&y4{`wkM0| zJZT^8Py0z4o#o|aGp2%;L&7*|Qi5ZhF`+85TTlx&Gd=o}jplC4Aw~dCkTATt8NB&HAHHZsiJ~+ zb|Sn^MQz=WRTt)0P$}iNrl0Xd&+ubYdgo_%{HC9x1*Xq8?(tpc9iO}2SD$~|T6&G! zlvWk8rE}fU={rkK;RtTw6x;BP|@Z9_R|b3r*Y0LhAyfTCrpFZd?o5$MOVugtBXvgtZ} zWsDw$-*Vq3o>4nk&rIz6^s`EzSPJU_`Gut)9EeI)s*oEU47+t2t zGOz!*@3=ZHe?0Dj3hz&;Q)c@8_*MRn9~VK#bMf!&*|P*j*;e&0k3n#3)p6TT3D-NV z#cfMu+Zx$Hzl9k#K3av(rv*BH`-~1kSqI@v>mj6NGZSk=EQ)2>4{!+}HnuXtcSY%# zoa;<|UVKM>@9cX_5aK!rd!B;;aQqZL!_%frr-sh=xM%7t{&+9B@ARo~teoRQ{W*S1 z`mwAgzZHI?zUpNo7SW{DeIGwz`OX;3#{KodiW=`@U&rV6V~NGzLBII>7z6Sr{lUJ| z%Ts;F-)Vl1eP@@$aqKTYlYa7gF&>UXkYDThXAWP|&u=|1ex%=8yJXg8*0kwHdIJ=> zuC%uBJGJWKm|O`K6_KWY3WAX9!XS34$a}ZzO0svXjz}@b{KBvZZ50>X1_P?A(iBl) zEcnoU>4GzB*L6R=VdBAyCL2BJ9>w>gPhQc_y?E1{Tv{=VqEja>db|e9^-Qo}Cx5jv zxx*JAk8h{&AA^UCdr8IQcUb7-eR7H^s(9yxsci`2_IN(9EiX@v>H7D_@0XW%?DIi$ z+dk%=zf~{(o$B9Ig8J74*`@@9OiexR$9phvS-OQ~Tex1S%X(x>`0FW~B$DhmZbz!I zI#5a4QO%@MUFb*MGE+0KEM_t67eF!2zxQ408^7s|>UXKV_LA+~XViuN?&s9|A>KCe zK(;V@x1h3Z@(&|rfcx18$PHAgh5)?`K$f=}s$fk|KU8JAt*RC*w$HH)O#h0Xi;lRP z@E|;+&a1;uKjY86@0?mXz2Z-(i;{bc))pts@zclkMeG}c6M#mYSURCEoV+j@jVtF? z^huKY`0wiZtNQRWhvhSFGa~ESGuO7?KZEz`nm>f?YrSxslz%^YQn6|-8_&h_pHL^{ zclrAlAnZ*MCPQ~DoH@ZxZ_grvj#w&V&|FrNR|;AQXu|fn zb4IN!d3EZ958!g4KAw?vr>0)Vt$xq`PL8ejpE?yjR(E_wZp6yevFGGYh|h%Wd{3)h zH~3KanG~2j7e2$iQ@nTMT`TPOseAk$`a{q-bvE3CvjD?WKjF6TgBA;rHZzPV4^5`F zrk2&@-tfMJ6cpog)!jX*Cw-o7UG)2z^G?3Q>pOWaboJyZU%&VAUAcz(+E)IY$1}Id z`xkW7>*}cgC3>~dHZ3=_Q9m_lRYh6VjH=Sb`KW|B7Pnyav?}jrB5S}q_!;fZobzs9 z`gHTLH~izLzC-O|yZxg#-goOqZ+r+hU=5W28ZdU#c)hM8zf}xd0Kjshcl4_1)kY|NSKw9^ZE4raFQ9eF1Y2Ab0k{g|IY% zfXBHIz(Y-}aA`UyM$60FN?SNCSo*SnYTPF8$Fz$M=f!xq@Do%roPZO4H}vCzo{V_B z5B>Q(?L?Tja$LPVY2&gr&#x)7R%g7AQe~O#9u$}D zLq~C2Ft=lXm{-jV)?mZxT+4k!%s^`Avr`0b) zO!Ww0052w?>Vc-kZ5LqMYFahQJv;|au>wps=&NFZne!`EG?$bcZh(FSpzY5>ahlG- zivSFkeYxqDjswV+mh|zJlMveP5&3uG+==k~Pu86{2SDmxm3?c?H9dcP-XFerm{yiL zm>ksEM&=G!-Q>G|ROWH2ADflfdT{WyN| zxECNjH8mLsET_XJ!D}1D&eWh)tCQ2zoltShwIJuYYOom#R*@g4q-rd#SMLCnb9Y=y zw+5KW2Pf6e?fOe#EaYj)$0xVH`wYHIkeW1x={-YEO)FWwE;mxzMQk5G1_h#d;_jI| zY)tOS#Y-c7{21Q%&in1Y1BlfW=n$Bt)goyOOllgI&(?TYi>W18N&-M<1Mo<9dw2Jx zIeJ-16RxFkhiZ=Ne&$)+kEiu>zm}S4^~-g%v8Ll&i$>k}G8Hck?Upa>;6`E^X(vu| zl?+E)jZ(!;7>6C@sY~mwXK83_=RqybH=b%fcJv3I{Lj=bwv~T&^Zjc-cH_g|SGTP( zYn9gIe{Kbet-!9V-1UslKmD|R=7)aBojZ9_pIlnnaojm}f4pye z{%KGf_mlk~D2G4)N-5KOwH+4OnKRyus|}Nmx&$C&NcYOcV3DmhK^-=g?r_}`z^s6c zpi|X^H>L@LFdsQ2MfV4|o^TU%v{mYG$9 z0$>ITcZf+miW@2`da%rlDtl3{JY00E72Nr_yW*GBQU&D$Uwuw})xq2!I(FP&>z$JU za{S~9Yd{4MJ4tuNRn0Z21T21jJGng>6Hh&<)avDZ`m(wVQ@iW;MPYmX+PqfaO=inA zobxD-ye!9WMDu!0_Jwv7|8AGJC-3(G+{Tjo>hP*R+&rx1bqdr@O~mY3f~99R1X)B| zTW`cQu_~Z;o%QcAr_>!<;Ml5QJ2e*Dm~dhdp4O19SfBDK$ zee_7QeT|>yQ&sB8$J6b7{Ow792pG7&b9ekcKpeLK)-_u9nQaU3T(~U)S^&u%`U$hd zJeTdf{!ioA-*i;hk9@nO=>MT>G9E5pzN{vF9$zl|`}|{auFJoEKyz$dyLt$U@w~Ac zxzX)6>i*g-Ye%Ws)U%1-)Jdw#v?_Jm$4RHi$~IWNF33FwNG&+!7Mf3X0Ax>mo7%;8 z>qoBt%I*K_=7-@-SvAJ2yGpI;#BW(2Z|I`f@~Rwql@C>wXI523wUE2yiYwi|72hdb zv!w{YW^*BeZ z>Amk%-}s-rQGJElYxmXu)o-c~{=@gH58-)i;9+d?RfX3rQj8`6&8XA>fR?qqDsF5J z@}q}Z<>1z4Idf#DO0KW^Po-IzfQ&qH1jyIM*nvGov@%rk`1v(Sv9pW2II0>H){N zvm0u2skv=+;osG(S5^B!+w&ZU_Z@Zw!fAk`<;G5&I5D=~Fh6?FdeV^qFVavH%7zx3 z&@rIXmefTEx$f7e>;C6saD((2UV7>Njxlcx(g^@2f58W^t&fT7>%LaM^0#l)eP(~zx9R>* zzn6BX?lZpl90B?$&XwtFx85u%?+#&X-1u}`+f`>w_K4o{+L~gY&X_-==*IEDM?P<- zRpwj1WxAjiySCC@XlHZAs(JX4=hCNIk01TVPwg_0-Talce}4VL&iPe1{x`gF8*r4Z z$J+I>!fp9zIKsWk675Hkt%|&Vy=;`eYUeYRw>Qa4sq)&j$~^*mv&SM*SJaU?5G=z3 zT3xxZeb3St{Bzl3`bpk@fE*2W)wtssj=`d)=_kNZTUO`rdXoDu++kVK!aIrW-u9dj zkP2IzXV6!+r_`tMJPM|@(!9-HYMd3?VLOzIaS$EV zJ}9-DtEw8z;JNfc-KXp7k!Z$_sued{D|`p@{>evgLW^HePd?RwoVu=`Jhh;1KX*{w z#_zSGp5FMthMrI7RX+h>fg_&9zng0}1t9h>?N=L}4ZRpI!d$y0NhGrtQ$_|qI~@a| zWkA^2xBDUFxLNi60B*gg8To7zj?;L?Z*6YbWGV3iZh70!CbK%qBVWF)bhpu)^tn`L z&t&dt^|XeisMZu{PFQP)KzDM!e8UoGDLwCpyx-Ut1oH%d4o$re z+t+%}>O;5d-|p70F@R}PI-?}P*(#2Y7qq0&M!R+EwpttksiHZp%5^Wt3 ztC90Ga7{PxO0;3$X8}?re&;##dq4WS=C$;fZIKs%KfGT>{}hH@(YpEw`?f=D-^oer@r~jJniUjAXZ+9RA8wwb9Q=x6IJ38Q*H!Dr>5c z7#!dC+G$7`0E*ViydoOv!J5PlvnZlAK+uB8Wr3oZDZwl{YatgQ0DU9Ml$+INwySM9 zDE+W?Q@3ufRvbSzyY1};3p!qhRfW@4pi_HLT@n?QUw#4@4_A}3rZJ@HJPp+I(0#@87))IkBtS8JPj6Z@G0Si>iaSj5G zg(FLv1GAASedOATSBL8PlA$k4>-t*0s1GF#e=Q&BD9iknQ6_B6lS7QD;V@iJvsPYT z7^&wTdrYiNb!k3y8J490>eAWm>o~RTkCRB&V3h^St&VVf6&BfeA?vn}Y$YtLHEoPD zDW(Y@*$~h)SE{JjR8c2Y=~khVC|4~!<91mp-t`$~s<0YblU8%@eV2OI@B0$Yo;v(NVQ zcYk*m)Xb6@!tchQmW#FD>3H&cU|sx@7oklHiDt`D6)X#aj#xZ*-0)~|r}ef*l>z20a%0QrfC+%K?{*0Fu7R5( z^9VP1FQ!48pv6X@-CtkBIt0+Z1#}Giq`P$|#(hSARp%aHB9=V9Fw0W2Hhf<3-p%RN z%~CHE2mIRg6dtBWw9isl>j$j9o#@Cz0c-BJ<))6JeuK5q8$}s6T^YC4sDf;XyGB=Y zPMf*lBWr+Kd}>#HWS|z`zxLxd&$|lLqIZ0fo7TFXA7q;*fp=^)?3>Q0NSy*HwOY>j zqV)O5xp?5p)zzvypR%Nx_tAAf*DT!X>Z)>4>=)xrf2+VljAOsFns|;$*yNa;w>_;@ zmGC*@Nu>Zbj$v9tV{7?^7q%_$3$TJtV9tX2Q=tA7XiGJ1DLuBeJzi-Aj+uf(0I>WH z+Puj0%0e#t;GR&-+d!PES6wNGewu|@y_5u|=GvsM`0aGXU&(Mzbb0iVEhm=c3+M-_ zNzjx#EVOg*4^I2*ru}JSt8Bb%;6B@3nLWf;R_|kG4_?G$3(Bt_RK7b>euxg2Vl?vcV%Jr@O=$0xzXX8;*=IJh#3!Q{{Qf!651=9Mox zVQj2L{wlQo{!vWUs|qfY3;xkZkJwK?r2uNAJlpEx;DS32AJp(>(>(fU6SVyc{`u#d z`l+Y3^m71@L{da#@H>56A60#QWd(gX1`CPj7t^yA)JIsx6#zhyL<=Iq`)Igx#xwvV zMO)9YAkh$>$wm!4+-~Fev7m0i?6MBmT==y{spf~+XZ!W%imG@xZwucU@)cSx?x(U4 zC~de``m})f>UGby^(?I}@)zyCpX;+SNgrSc;lQ77L{9YyJ}sx(0Eig^NFjYyJ!sP0 zmtvSibwJH?H-V`mSZ?*Ti6wU+fEYz4ubaQOMzF;VDhaRv+Ady)=&W6Zbq+0Li2mjs zt!}`qoWV)@*sk!f(O;FIe>plFH^C7M(Jw96qGkZ775YQr(HzwCzsc)Tx&dHY`<&Lv zquSV>VR{0za$-a@>WrrI*C+1O;GbtXQ-b>zA;+tDsxtzbV>dGoaDwqm0m z8xGuhtTa&D&zG@S+^ZW(lG3`ZhQ9^9YH=M(pv5@Kp(Gyes%x;ItMyy{NQ(VSUlAzq zD_j2Z$*ws{%k4=@i8@WnN2bAR82p*Ev=$?MZC_Uz0M>#2hPsvYjau9n3~Mk0_R+(} zUVgzZPfFVs6M{3 zsWR(b6O=9Pr5RZZ7jxnBC{dUa3a$iQHkqHhSc_&3CW<=NvBw)~Ww_#+>CklM8+xud zOlR<2z}>DJjY99sW3>g=q+}w;f>jH>#&puG z&r^XW@uOh5xACvgg=jzEk#%fiJxWHdRYp>`Flxl!7KQ4qXO73ZhJ&BHQv0fXaDF>S zf=H}9wDsGiPiNyA8}AxLPd<$I7V(>p}N` zn(ePZI=64D_Mk1iNLRt$c0(_;VITc+IqrH6?21D-2ITffP!l^wKx+-NvYH71<{k;2 z)FCX~stA+6IZLY)AXn5sOyL9{q)?cZUj>jYaJx~|*GyZ#qkCJ4>2`6g6@JyC|14VK zZwD$=1F$qeuZ_=!nI2@3YV8Af4FNYS zo(0VV{%i;_F=ve(fn?Af7+XE9Z5IGnnJO+cv|tm1Z1AA0sbX6r^}}32Faa3}o^jV@ z3s;MIi_wbVYwJpd%=GAEXM7H2D9&_3?LF>mJt(!5qqgt>^omMFeQhFKh0S~yU+!J+ z>3P83W&$M(6W1r!Z*Hus8N1*YY~OEm+Iry-{7F6BqYgj>k4(MLbE>zbqS1-~NU^s3hU31`ReCIlpm$au3b(a7} zr6Dve#!bE6=Zc>>wb+c+#t43IyozKQ0FiS1%>qFWF3PDTqtnKQT5raF&PINbE7#f2 zC=O$;2av6;HM>a2=$I08K=iT+E6I0#m3qtH{U!B&Oj_WRgBnpasvK4srcZ^r02ycF49EjbI7(V>IOyBR z-f|=5Oj=~BQ*4=H>2t0Jfi>T4h{nC1H#JvMXV9o~2qPO?%(Y1S8BDCqn;}5S!}5w7 zrS6SNU8IR_;@}VA%#<+<6x?A_{R@;r-$m6PfIV}B5dnQnvpdycehTOdQJO{a3T>Xq`cblF; zBaIukqaFn9;dmR_=u9t5v_GeV0Bjkek{YGxQ> zK?ypbPN}HPm?6Bmn21}jM4H<7DYQ2RzTM8k1Mv{l1|xin8Z?A;qeB&$6{^B-&OnfC z0*HJ~)p6FdtSXJ^7NmNsO^VSd3jpiqs@+XZ0LhUUE2GVjIH2JoKZ=xTSeQBxDs2ai zmu6QVGt1gY^`W7&%p(+qKE2cUv<-<4M_ZU@QoCF-okDowZbJKc+=i^lt7HdQwXr%!oH3zXO z+e3@)R7ITI7|KkZmp+NW_BSirsPJ9vGyPc2bQ?|p-j&{uEW=wot==sV6CKD_;$`pp zRo9*ADoMRg-Ki1jbx^!Zou(7NY5x)c1Y_`d(vh_?#YU4(1$r_fJ-CYd{A8{VguG*qB@3v^oVJsDJH((wOhG14O zxDp0Eb-6AGn#BNQFcrg1zdknyJ#5RlqTv^>j~tnhYZx|14uPB;ifQhTlke;`#BX;V z|DI7l5CTDHnJu62lLgozy77U0WOrF);}lgF>y@VTpTGDC$cBB&r-u~iU+9zougUP8eg0>v#Dynn~g3skJt0d+l zhwQ@Sh4jn|R_gPB-Uj%)sS_9P?L1-r|3{0U;FlFgDtDDd~ zagpI+P*e4^O>xW+)24yrY00!lwGU{Wc~}@&foTD2qfAX>AEf+Rp++`hc68lnTS=h9 z9D>jsA-Ex^sUt!=H=vr5LJ|V|hM`rJ1ho(}2u$Nj#dysMH{wrI$fZq>C+?aAwi19g z4@-?gl6@%g$lCzhHh?QNz6Z~07taXuRtaEL=+_|8TM%U3xMBJZU!)ViLn2R`wpfP{ zjP1k^~|a@6iy zWK7$^7`BSJsCcbe=`^{-QI1P1tZU_fwxLfN(CLdU>=+uKK;7$aT0a^(+h|0#Ut;3q z;7%Ydp{`)~xi+(@LNqpw^@9Ov;#3*1u>Rnp@88ONJ7vb&$oIOXoy$_U2^^)cc5&>~ zAyWA^SmDv8hi6VNbTL*z4<3Lev^ty-+IS83cD{s9vbU}`!3;!H+_0_Zx=?5;fLc2w zZHArQHL!IDPT#_H1fBvXXoVOIc>A!;TBf0SCLgqLg%7>o(s&$9Y@Q9>Tnx|!sIA43 zsTxCfC)(ju#T+wbfVa*T;)cGl5*C$%GbTUlCjDC_9Z(SZ6wu@%bwd9T=rZhwToU?^g^ETEF`Bqaz0m|>K|z2uql9d4dfmu5 zQ|LRJvy9crb;`I?qmxXEsK&CMhSZ?~St|}96~{zcR`!D>o3mss=U-Vh_*zk0H?A4w zE`u-1$JW7V8hlg*EV*0~?*i-qaAjL{Q_RF+ON;JKI+p-G12PZHkaC%B!_rb6uhD;_ zi_D~eS5?IfOf?dFY*{%E`?4rXO|U@W6;!c~by2aFinzp?`Vhd6{z6+(c>M6*R;nlN z0XjM1$aQ$Sde?!>(JRMdE|OTOWb$H*G37yL;KIT7k8r={inuH`A^J0)J6L4}#z>Td zw!&N(Z8|d(CB>lcQVxs$z;!Xpd;xC^yxmPqVo;B2RNz?tV6XCnrUhQ(_lgmeI~ZXY zgC^dtFg~uUg(75 z5ce34I`}F9Vw-dZ;hsYY+Q3{$Fedurs9aLg9M>b!yV#&ph=Kw?yz;99Hw3M1w))=Z zOk<9bt-YITrX?-^4S?@jZ_Uk*=GCF+H~f`$rh|X>IrZHB{pQJ=k75j;*OMTS<@zre zxT$V$QHWp}Pw3Pm}RI){wMql|$aCg9c!Y|q$o>dEsJ{u}Cp06vgPkOr*ms-#|7gzbdMg(a?*-UKHJbM-iTmz(rW zaun%tB8Ta`+LL5mdXk!SlC_AzFGdT{Zo_-Xf})+29|^z3eUHz>6@fm$-;l_^+}kQ78!LZz)> z=edN1eaWqu5wpMo>LTcqGn@#R+1{nys@xoy@?fVly~U1efL<9D^KRzQ4bebp>Kiz` zx8QSW?t?SW!SZQ{DWdEk*P|SSjqbzgJ~XWsA8=xuhJ}U-s$F>7i5mX42Pj(_J$X)E zE7u7$W<{4igmX$jBWMx8@^*Fp(L?L|Nf*Ou_P}1*taOi0Rj|8ae??2nYe( zD+qL9UPbMb0z4W%6=?L#d`ns~iA;$;L^2aC$TCv4S}YrE!V&>Ez>38&KH^dq&tgBA zIV`;jvn90v3&Y$lIcXqRZrUmW7s1sTJpUmqINaZ4B-Z2*#B?(QMW`fx#0a$s4=1U@ zhAVIvnvqyw;lAL?@Gz@Bj%ZjFV}D5}0={7)vDD&(#o?ir6eOKlQ5UoyW*lydgWnYW zG*t>}PJt@TJuQN71)20T(O4~ey~E7Tcq;Sr{H0xLg{VU!M7Tnc??f+odtPhu!n zv-|w8Kfu^TA7Q$9xEIX&TFE8t8wX=k-Lh4>nR3BB#vwp+Wy`6zt?7&Em^!|)64t>< z1f~j6i<9yz_uqC{WMeQpy{!CuenJ_B->-ZF?#{DHcMdAQ0w5E63k?dIPe6-8_i|g% z+d!j7L+W1~vP!bv%TRw|L*04-6fE8|1O~H2aZw9J1*ZkM3`s6bAoNbegQ+2lfHkoS z88<}hSJ&lc1*GcFd`NMsK{Nye;0I1k>WH`+ymTOsf>fd?ssW9H=Cikzk$>!u68)Fi z=o0|k%vV3I7T@)hI`qc6J`%Q4^xEfivkX#gk7)R&CgvQ*R=l18S5wR@m@KVfeF%5>=S;D&<@ZCg-$+K){Ok~{3qUPi z@m)-?Xf}6^(NdK4S1~a%SdSw;!{QoIH?q|Ru%;9F1e!j?4PyjgQD98s6+S?adAOdo zN#a~X_QEPEG?_6mcsaI#E;2fcOe`bC1(FeV;9xGA1YlR9DFK-km(0NmDT)Gv8T)wg zup)5BXr{u_gC&!Kn<@q-0uYoHz*N)1Av%C7GhAs2;L@P*V4+nJ%SVXWAyzJH(^fu* zRm0@Zjj!gmwsLEjf*qm|3mf8CG@U0Xb_`b@-7s;B|y{^n{xG&)Y zhMyMx8N(67+`S3xzsylpfR*GQg4?2EK|tIx9jb}GgeSa?+oL1r{N@Q;!ztz6d6 zD%D9;Jix$eU|!iKK7m!37H*i~PAtHDt_D>$a(JGtnu^Op@`BAw#9kZtG)!VMw6|4r zqcF`5?7rC0#l9NDBc1ii=#tht)HUM_!DqM|A)~(Z zMhQdj$5vYCqIef1GG%-LVu1O&p8D9v;{F=UIOUk)+wnccN3hhifSL-S2OyZrCeFZ|M_>RI%A6;QE(8?ug@zonC^ z2TgkmEcPhXWzlT(i$twfzOh-gy93{kHeF(FQ3>Nb1PE=KHdMx;-q4T-jJv{|gs&}a zM@3%H0|LPhHP3K6rdY-Es4%=qqe1e*if}xLW{E3>*U@4`yZTvZ0W-0#a0E;@UxI7I zzA9ol!lEq6JwnICt1Y3iS7kLUfFUK=%W4F0gGOH_U_w)9qL?FYBO4S48^EQ;jJK;B z<=hN?3tQ^&kQ!$n3|S?D%$ z`Ych(i)M){?$wjvjk?j|j5w;PUh~y+v^uIxkfIR=aRp5q=CK_)(a(4uf|%ShAFLRn ze*vY#)50w{#%Z^*dl5l|cPqgSu2|Pf3F8`yA3+-bGyBe!6X=Wd zyP`q>xoowhInc6B!0<;nU*Yz|xUe7^s}d-!1>dj_HWkCc*l+gH#emqP!UQXdp)HGi z4r)MLZruV>)S`<4!%DmJ#CI#WPSg=%$%0j>@!@K}T0X51%MZph~3CjU?36wnW(!d+b z5gunOx@8O=mW0j(w8hg8AC0 zsu6hc5+||?Py@Egg(1f80t1<7*F34{FC)EpPMuUMOBei|iHG&_@_j9_*fD9RL-2JC zW+yQao<5}X+BK!O7L;E9EC`2L0NK)Z0^!j>+4)!{pcvz%sp8=PgbDmRrit4Gf^}8DipHiz*OLo3_4lldOiagM zZEag%I#_VN3KpLLAAu7(qzzUfuie&t6Oi?R0_AIJB$FPl!K=n!`g--md%mn*lJgq3 zX^U+9{$GC7f9MB4s6K?TvWgk8212g~NZC+&xCOzu)oFvM*IOeDpnN7;@va5xA>G8q ztovvdvzvBNW6Q7#AfN?;2}9AsY;#$Zrcq2A#M2IO9KBGHF|X-)p{1;7m$4)d1Q{h1 znFlIr9W`s?FVGL7Tk8n>j4Bi1A?UwS{01V^EMDU)v0eH9}w77l& zs@TQlMrk8hWz`Uvzv-yuSuUgCayRUYVlCA;;YR|a3iYkx&4IM1VNWX{rxj0K+mYmO zP`#k(l??Tlb+~vMblU*PNW8!mo?$yBCGQ!=iT}GQOS&-WFz<#VSPYRoV-CW+>KlR> zNMqt9C}MCRnEYi7;DUKuQZB@d-l{k@Lk=cL254ru2>OHFHmI<64lGSB;DatF8Jobo zSB+HB6DVK?^`QWrlY=D4GvC1bv}zQ$GnFn@n|@GM@QKVn(sEpk2S>dlm|c9~1%JE& zXgGGvO_CU&ko=4fv@rUPV2`>yJwWW#g$c-sg9cWataV#@3r@TS?iE8zuj7e#m6_$@ z=plw@gX=F9tzxkU^DWK*SzCtLOK-4>D>_yxP9waEfQ0yP0v_6jT4n-0LKOzDhUR0& zF}kt>L;_%1<|EZXK5jKBKU38LMTRZ)QA1s}w#deQwm?r>7c4d@01BaE1yr^CC3IEe zOqAU&*3OEB360)R$fto{@#;^wajDqY`QMw5Q zIWlRHg2d_@I#o))VP{M?fhL#$@NsP$B~R;_*5WSVn>n* z&yM%k3T;lGrzRYdyfRAFqmvey*t)#Q7^cu=H7pzXd2w1=(RgtH!v^z;78<;0Q3MZ? zjsapZ?;y=?SxiC+#fGmdOY#)~nNP;l_%U>M-}SF$V+V*&Hhz^ajc zLt0TR`Tz{*6r=70^a;;2vgO8Ut`OvGg>{3o^F}}_<9S0-i5;^^g42OwAJLIl7PJfK zJ1qypf>Y2KOg)m@4J`}wvrfap^=K+u+042yz}K0LfxaWseLAKPWrC}U(edB`#NHHu zlH2Ko)6o*N!4c|2wA4t(2VD`3#d_sZM<;3Zf>W5+ps7$$ZNs&SAzq4}K*P<$sp}Ik zrW$s&FUT=bQN-ngyio9mQ6GWn=s1K(QS(f=fm(tu`OA)$p(sNY({Dw%t*+n_X^`HQ zb}v10v}g)^0}sv#XA2|*jaLwD99(6U&Oy?^Z?QR^hA|%4g;`q%xsfj z8iN<9s7k;o;h=+ZJqe$=rlLX<+6du|N$PVa>b(tOnfDPYm?dNh;haDV1QU$uMA=T4 zACqCQdbYKFjPW=svMe7Kqq(k6ia~C+0KR44uML!%zlrhDUec<05a)g&Vez0HBwM=jVo(ltA&J|+XcDH-==OMU`H@DA=V20VjNdO zk24<-bsro94U^(7T=)O>e)ZXdGl6bYucG;vct+D;c4)>gklQAa00D}b>*#D|h?r%* zfkuL<52@AGpfeyq%W}&%I}qKVj2tM2hGD>PW(T;_5Z!c6zzQSbjR9Sm6adA?$7RZx zC~#*{|FDtdyui%IaCVHL;?%<{RRnm0;#>f`V-Let!hXoYCPIbnT#F>9&lLX zoT0>aA@*f^{;xA|K{GyE>55_&^(uONt_zi`{rk;VW*n*lSR z3ustDr1PRuyvu$hzzEq)bRx1uqQE(!T4T$2O#(fLElWoT@0Ig-{@9ikY4~9cjs@3K z0)&M*5purvQ_E^L;xZ{ZN_+8E^ENPayFe)+DH1r1;Y``FBTiFOdoRM^Z zB0w%ZCz?T)c|Kb{LQ$)EOSn_gk?>?Py(?0K#0V!m9zc}$4-XVj<${GM5l2yu?-vro z59$C~Dh!?&GY4Efq!MnDOY#wPx`@Ofehd#Ewp`*l{vglNMgxx82oAoOCLeA+#=c>E zLL@XS3zg!;45;xEm*_+l5UpJz4A4)iQdAxQw)AjITr0e67(FG8Lg-^qs<>VqgBZ*q z-M$TUX1FoJNKY$0tNm=&t~SzrMlCRh>PTN%|FAi(j>9^;L=X!U;xZr9a$qK4mE8}B zvE3DZ9}*Ey0{`eIqeD(Bm}QMaTt}faSSx>(eli?3vj|-f7FfClWvL_XXWl+fBOgQA zwMZr50l@;R7~TYnI!d*W85vXJRv}W+l7TP9Q6`4AxN&_jc=<5A4AYR9Se3PlH>&Hy znqbWZ3(W}Vi3P_IDc`B&Pawz#OOGUyfLM5Nl7E3zC#^6J2l~cjAjyO@AqLk7Hz@*K zfxf!tCF)gIs=bp=oNi6hw4}y#2!_#|Oom)`5hrjpmGB<76R4)R!Ero- z=>=oQKvqE0(k3%`RIoODnm|2}m8=-!q~o{f^+Mnf1cG-=!vMY1({saB8|3q# zVbXi7MiB5hP?P!}!{<0OMliyPm=q=~Q1C+qIYO9`HX1>ZHw;Iy6(c1_*)4Frh9P(0 zv;oT50LRA(ykBY4(;oE=@tL>+bIQU?1SgGykdB~YL0m9S!G$Wr0w7Wb~a znvWij%)*k?{Sg$5N;jHtX%0%$T(H9|k93k#U5H4)<|7rdrO;p^duSw{P?iet0mwka zGw|dMR0ypRqFZ7Eea-a}wOdCh%W@<1_Gmi54g2=VeSJ7Q>i`s%B3m66emCi9$BeM-a6qpiVK&KW}eOhX` z*W4zy(RH6^iV_>DA0wq@y_*D``AP&8RYXy}2>ILh68i zsy3?;t5KpFak6NAsD?lLNpIl{m)C5D#o^&)! z8Su22u_e4in=Um&i2gpb;))ptpd1vOMo`O{CIs1P_MWErb(a6eANB_bG% z@GDpN9L#w)?zGa?jW-;cv9q0pWMQFWJMH_uuC;P)tpHViGrzfZY4F)=FJ#Z( zx;nbL4v|Oei-Ii!8wDRU^f$*qbAy=(<;Lj-lvxNgPd6)oag^abOf07D%!?Eq%`;GI zcFVyCGkH1EO`As0j3Em_mFAx6C$1rB!N|k)#x1DO4cw+C7dVk-#65uV#;6A`mWB}> znVgswzn@qeqOyn^MFJ*V;MhveXhr`7vq~6=IH!sv*eBMB5sHSHlq`)&YPVlmi`6Ytyl`7>yzhB8_{|kJ_^mYzM#;gc zs0e^;!mnoNArmgbZ1MD+6)MntRZXNZ{zeu^Fy`LLSQnlyk$WR615^sD0k2%&zQ1i+ zU$NiM{qCbGdBcKAA6YQEk&OFxuh(!3(BJHHt17#ETW|c*WxxLOFDm8>^~@7rLMTTJ zts50il#L8_VWxe5P{mziT9SdSis0?ds#Qmaor~e)sRm$~|*@U5Q6(ZS{Q503d zV*_JJ2Xz({_>hKgEQyVLm59e5)(_Wgd#-v>RUKSS1xNTqE$&FMKaAuJsk16o65p>W zE@A4qiX3VIVm$-jmw|JH0-!PC&8XBO7K@6RlN94?z*}aFRiQBm`2eRd*ErB!3M*Z} zi~d9W5cEDWE+)k#1?~qhDERN=y zujPw=Tw^V07BBB3yT=h;Z&%O0BYN==d}7y>erzF>c6n}1=>^y;j9@G=ROgPUXmb;) zR~!2PSeX%!Fpwb8fUEXfq%*|I!k|=~;u4`q-=h37*`2fw=BW4C8pvpc*`%J=uHIK{ zgOpqhreu{1vB5FJ;jN?kyk&hZei!toDO{iyCH9LC5q|_T(wzh;AGA?0r?UR7iAUSQ zeQ9Hucknrd4>P)SAK#}Ie*8P`S)%d2+Fiaezr8(v&oT6;|8@COm)DA`u*BBjTH1)> zq8B%^ex*12NxGKLv5>!pb|Vaaa*r1O}0a1wC%kae*v97~i0H^LlkU~;BTG7fsU zj>UdX-_m{aktbSD9e$#H?6LW1VP3t)ZM9fkyE^*Z^k z-~6FZ;u4tCbOgFswD#aTe}r z_CGnI=YG#o)qTg4ss^rC)d*~Zk6rdFKl*XM@c~GX2v(aKfk1=D#14xr&Cv6q&(o2r zT6x*)q*7*3dWfa>ligfF=<8m_kyCb`ERa#Ec?{08ZWZ86 zzzKET<=Z`Xw7rDwc`qejPM&mU>H?gn`Fi@azn>8N=bL zP5{{?0El75SxmyeT?|?v@93MnK($1dW0Hwc~!wpt;%M6uY39V z+r0uj##_@gBbAc5rcdm8ZRImWHY!0P45L<3fK6j|umNt-C<4HFiRv}*ql1)TN-JCk zOcqNzr@_2T7@jGBzJYny?8NQP*Uf(Yo1SVv{n&x@z-uF9U!pC<3-kQ@((aqz)UWzm zA6)yjkAABEsTZ#npS!J?AKr1*4Cp`&cOHfemz6@V#p8=f=0H;)jnWF*IYv#HXCSFZ zK1$ok2rd_JV{w^#(1$98)z-wbZK?FhM|Ah=-aY>PX|3(^>3I5O-tTBv{^lpcd>2kp zlzdW#j-mE6;tqVz8}+_F@@A-Wv3f0AA+;aF>%;xgYoU+xB&iI@DX#7q+umAFy>I)7{4fsOEg1^ zS=ORtTH{2PJi#`FC8n7!8w#v%CjZT!|5p9zBahxsAB=isE&tp9%by@wR79~5UvOd+ z?U>F4u>D86My(EHG5gV|=~;2+cqof48Szht>d_ChIQpK#*Vjvjm-*&|^5Y0b7TTm$ z#_i!MUYYae8m7iEs0p}5(Iu%Qt)s304BgDtP~6|*24pq`s(@CK*)#w^{Xhr^z34?R zCcuQp43J5gWj_Q5OHMGHhwGn&c;|o_(~ex|PwPu$e=NiRgNQZ3jN3#VE-Ya#oq|>z z)9+?vh$Ya2DKU*GMx;S2Ik$Mciy~NS_>kee^qKKgsSk9LL^$!-Ph3~MuXt45w*_<0 z0FT-!>F+ph{0~5uQg5QB2W1VDTb#{MjRw}*A#NdDBLFeOmHuYHU}#VXMT0s7oRa`8 z+k`6Kz}2;&0;DsxJ@buA?|SoFyKg-noA}jh-4EE>w%z&0#dp2qtLMLV>r-17pZm4- zU;E^Z;@WN44Fe7XMvkf=B1X(S0^}Nn)d7qd@(jGk9VlH3E(4}G07#3U587d?^f@y* zHDQ4@)h;(Y2OcIb zAAagK%t5G@9IL(vY@(=aVT3UpfId3Us5J{Z8RH~AXYg~0KX{ti-gBkqeU;2Nd@BM?v%u@Tn_@Jf)`I>Un(I=-tl{_LOlrqTJ2 z{R@BV_6BsNA+wum`c>)PU_7|RGv;DxhRZTk1a1We(n5TLwl!Q|m%`p`f*@dS>1O;l z{?gm;7sOs^t3LSQf9C$fuiWC&5@TB?FW|S28)mq*uA4)yAR=(!(Xo8g#)~RpvCqb~ z=sOEAtJjkSivK>^16dISF{vq&Dz^bT5so3vzGOE9Ty(LdToV>dzqZU6zD4yfrc(s_ zvsgffDJW?MF%Uymuz>yLqCdvUaHWKJ7Z_$iP^0?ARUK09O>%07%Y)C2&X#bIA)6zu zK9!gCdsu0prF3x91%sae7>Bqe`sEyhn1wJ3K_>idCK3vnL#zZJGlmtuO<4|`*51zm zViGbXK_Jzjcy)=9$9^#h`5V)Tcl--DOR@?|D)by^u{N?9G-@c}G-acKYa}HtF|J!- zTsbstuyN4FA{Iw6jzgu{wVl~_F23_EZ|#2BiP$8st(EW!8UgK@*{^u(8#~9J{J`3; ze)Jp!9Q3FJo^D1`q1~B(2MVR?JdTaYqKX$nAVp)?mqKZf5zv}-r#g3YehxP;puAl zdn+>&GY+2X07{#aO@qymVl0%{AMx2fFbnda%`v){mBb7qYVp&|a|sy9{^`Fv+y2Y{ z>7Q0{)R3@g;jzMZ?rm^Q?e*%utui$;Gn4$qKlS#}>A&|Y47#zB=~NOnM9h+C$d6G* zaoIf8a<9VYw6rVuzsXKm-$L(N>WMcjMeq8CuT;C({Kr4}@AJR)cmJI@*WjsELr846 z>3pvzhRW7rYC7E|Bc+sXt(BL{p?VL>Eug!_+uc5t`|egTCyY@%Y8{LzGUfdy-n+EEY)b0an_2S8i#Ei z_!a>?29Q8V`tjoG$&CsuU*Og2?OM})#cldo?W7lX{@WP29401LbZM?52FC(@x`^W@ zgnOe*<0wx{JxG-;S|A!*z+RS?Wn@_wghN+5KMNn&Q-AU3U;IN~0pNH&fY@{+puKbP z_rBwA9Q*IS<51%Os4YE%o707-2|h_jpJW$eqyy!pSvc2V&T2l=Oe$rR@F;t_K2zuw z;`5=d<6W7m-EP`<;DhS$RXB=A{@XV_bPyZ2XrZl-{lGg-q`9lM-J7-EX*D=Tbmv1qhrw&4Lv@!cS9&QvHyOvH( z3sxDF$1Ew$0G4)@LS8^gDHvDEsmisEyWel-omR{)#RZa%N&urBO#Z^nt>WLG|K*@! zhBk4qdUfYswd3ON7sTpj-tpC6YJT_Ik3qC`;d#TnP#wsPj+exh*oGPdS%yE?M&CN1 z^ytfPdp>7;2g*xF@0;J({J!OHR=e5ygVp@|{^8GwPf+XtrgyX9YB3X;qgqPC^uZ*@ zn=CyfpOIRmfy7i*CuJ?!*>JOhU+KQ&>q`QeeEUq;K0CF41Q5G;F{~$BnFna_w$dWo z!f!4Byt3^dZoxOjpz$h~Ko8Yy20s=7Eva95Tm<(t6aU1L`+*5b!ykc$gJx82Kl<28 zic>}zif>H_6uS*l4>sWCL-* zr7t-lm9K-!{DTh5&?bIoJ-**lfTp*f!UV`N*o#c);BscTGfwBg{t+;0l)wiJ-KS_q zx@hB$wY04uTzwZa9%QteoryY2-*))hzW&<|ecOLRz)-K-<^|CH^pQXFhfdC)d>i=U zSqKscWP=H*nI^l<1c8xFIv6iacnVuiTb4&lxxffhrwM;Q9NLEY`avMOUDw#5AOvk! z0n85l)njV$+aFh7$QJE`=KX_TZyHbThp+=+@%{nKoSMb`1c<4wj~4goH~!4;Ro%BA zRS&z}Ia>f``VHUz&A#!}LCZX77FMN%fo!Py)pXa0eZ+-7SsXljo=os$}zEfx_ zctH||_yNgUAcnRWC%4td?0v+jY);chb{rnEXQt!j801k0eB5ul2awf~E2<8^KfZnI z=_6CYGp87}n86}j#BI&tb(v`@&BAZZ8D-iD#OX-Eh7o2E<13c{aH*R-t~?@aPSX(wPHOI1}S=4J-XwV2b?^FhA#}3 zR|UYTBBoQVpc@SteFg2AYc-**JGcAPqSg>5x~&iWr6YRjI}WSYL$mu@`qBU4ZL}0A z&@chIxG}+E^svyM_&?sRk|VpG0Q;V8hp?{$MFD2^sqg#!rnxu=*l5Gg)3h4?T~orx zo28O(7&I}SX(E|5EJ4gelI*^Z42)eQi@xakw25Q`GA?9(=ENQS^Pl~Y+8Ff4SM$;r ztMA_R08P)$wv+e%)puyl1J+Wtx{I+tgL%;fDchxW1~Z`zdBkTf7B@d5@WtQut#2}4 z`L;KxU2N6A`GtR5eeB{YrKe}o>L`L=02~=u#auVw-{9&t>)XT3u@bi0?D-o~1~gb? zZ0GQImR8g0)Bg1MPTgl+vb%t6y3+LW9iP!hb{rt~*!AsacC~&jp#L^k0*I~M6f4LU zJuaXG&;Yj z1y`$=lJA=fd!v~9_*tQ1GKH+(#DvB^Qwb==WSB{WV#4?QtPJ@SV}KO%D8_}Blz|BV zkXZ}Tn%!mj!i15El@D1zxUf|zSuAa3L8X=@0v2F?-$1s*^74M7$xUo8e+Q|^Ou_wf zz>4cym8{pLS?fsK%&@YSHzV8=O!jKjjG_WsYzaycf*&5$C);m0@?SjmpMTR_G`FC> zm|CsczODP^Z#{MB+rJK*pcpY>Vf9dB&wbUZ7*4FCCcIOrvk_=U7OqM`IWn3vg4P~! z!S=3OWQt{)(ns5B=})|>3@@*FYrSbsEq(VfFO;WeGIW3#DB4H=_6e0f)>U7Kb}u15 zHe�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 F{{et{IHv#r literal 0 HcmV?d00001 diff --git a/showcase/minecraft-complex/public/textures/dirt.png b/showcase/minecraft-complex/public/textures/dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..d478f1e085be243c100c6347f524a528f6f378b7 GIT binary patch literal 353 zcmV-n0iOPeP)klp(^VbIg2*}5G8K|X?L|oO(HRJ_BL?W3IJ)@nzX$Q zaFPj$w}D({a#^noB;~&5TxNQaT;_9XU^HW+s(gR1NsbZ}7&zzd@U+d%U0lsTch}oc zOZuyk+UGJ~n<(J8Y)t2HHK}BIY~oPQ%_7Bf0#cR`#RcG6HeHHoRA}FTF0Fq9X?I5x zMKPa>0*Ku{R!*@9{j{#P z%}nZjZR)o@sdeWSPia^GGF&<7t)`a|YeT())7kYQ&(~V(di+cc=1sO&SW=<2AT2Ul b;i~+HPl+4%Y!R{s`i#NT)z4*}Q$iB}N`7!v literal 0 HcmV?d00001 diff --git a/showcase/minecraft-complex/public/textures/stone.png b/showcase/minecraft-complex/public/textures/stone.png new file mode 100644 index 0000000000000000000000000000000000000000..2d0fa452b845f04e466161bb7d8212afd39087a6 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt^9JzX3_ zEP88$4+@ZU^!K!=xfYH&d8ZU3$m>J??0Gyp}PLe>xE6S#t|-4Li%&-Pllb^;`KNy;q#h3 z+Q}XNZs_(V`?_D6?zFFYYD}K>dfN}diFS)**WNS_*`TcC)~zjN`R_#EPrkBeGx*O( Wc09^X{lf$F6oaR$pUXO@geCyL9B{e- literal 0 HcmV?d00001 diff --git a/showcase/minecraft-complex/scripts/generate-textures.js b/showcase/minecraft-complex/scripts/generate-textures.js new file mode 100644 index 0000000..c78a25c --- /dev/null +++ b/showcase/minecraft-complex/scripts/generate-textures.js @@ -0,0 +1,94 @@ +import { createCanvas } from 'canvas'; +import fs from 'fs'; + +function generateTexture(colors, filename, pattern = 'noise') { + const canvas = createCanvas(16, 16); + const ctx = canvas.getContext('2d'); + + // Base color + ctx.fillStyle = colors.base; + ctx.fillRect(0, 0, 16, 16); + + if (pattern === 'noise') { + // Random noise pattern + for (let x = 0; x < 16; x++) { + for (let y = 0; y < 16; y++) { + if (Math.random() < 0.4) { + ctx.fillStyle = colors.noise; + ctx.fillRect(x, y, 1, 1); + } + if (Math.random() < 0.1) { + ctx.fillStyle = colors.highlight; + ctx.fillRect(x, y, 1, 1); + } + } + } + } else if (pattern === 'grass') { + // Grass pattern with small clusters + for (let x = 0; x < 16; x++) { + for (let y = 0; y < 16; y++) { + const noise = Math.sin(x * 0.5) * Math.cos(y * 0.5) + Math.random() * 0.5; + if (noise > 0.5) { + ctx.fillStyle = colors.noise; + ctx.fillRect(x, y, 1, 1); + // Add highlights on top + if (Math.random() < 0.3) { + ctx.fillStyle = colors.highlight; + ctx.fillRect(x, y, 1, 1); + } + } + } + } + } else if (pattern === 'stone') { + // Stone pattern with cracks + for (let x = 0; x < 16; x++) { + for (let y = 0; y < 16; y++) { + const crack = Math.sin(x * 0.8 + y * 0.3) * Math.cos(y * 0.8 + x * 0.3); + if (crack > 0.7 || Math.random() < 0.2) { + ctx.fillStyle = colors.noise; + ctx.fillRect(x, y, 1, 1); + } + if (crack > 0.8) { + ctx.fillStyle = colors.highlight; + ctx.fillRect(x, y, 1, 1); + } + } + } + } + + const buffer = canvas.toBuffer('image/png'); + fs.writeFileSync(`public/textures/${filename}`, buffer); +} + +// Generate dirt texture - warmer, richer colors +generateTexture( + { + base: '#8B4513', // Saddle brown + noise: '#654321', // Darker brown + highlight: '#A0522D' // Sienna (lighter accent) + }, + 'dirt.png', + 'noise' +); + +// Generate grass texture - more varied greens +generateTexture( + { + base: '#4CAF50', // Material green + noise: '#388E3C', // Darker green + highlight: '#81C784' // Light green highlights + }, + 'grass.png', + 'grass' +); + +// Generate stone texture - more varied grays with subtle blue tint +generateTexture( + { + base: '#757575', // Mid gray + noise: '#616161', // Darker gray + highlight: '#9E9E9E' // Light gray highlights + }, + 'stone.png', + 'stone' +); diff --git a/showcase/minecraft-complex/tailwind.config.ts b/showcase/minecraft-complex/tailwind.config.ts new file mode 100644 index 0000000..5f06ad4 --- /dev/null +++ b/showcase/minecraft-complex/tailwind.config.ts @@ -0,0 +1,22 @@ +import type { Config } from "tailwindcss"; + +export default { + content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"], + theme: { + extend: { + fontFamily: { + sans: [ + "Inter", + "ui-sans-serif", + "system-ui", + "sans-serif", + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji", + ], + }, + }, + }, + plugins: [], +} satisfies Config; diff --git a/showcase/minecraft-complex/tsconfig.json b/showcase/minecraft-complex/tsconfig.json new file mode 100644 index 0000000..9d87dd3 --- /dev/null +++ b/showcase/minecraft-complex/tsconfig.json @@ -0,0 +1,32 @@ +{ + "include": [ + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "types": ["@remix-run/node", "vite/client"], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./app/*"] + }, + + // Vite takes care of building everything, not tsc. + "noEmit": true + } +} diff --git a/showcase/minecraft-complex/vite.config.ts b/showcase/minecraft-complex/vite.config.ts new file mode 100644 index 0000000..e4e8cef --- /dev/null +++ b/showcase/minecraft-complex/vite.config.ts @@ -0,0 +1,24 @@ +import { vitePlugin as remix } from "@remix-run/dev"; +import { defineConfig } from "vite"; +import tsconfigPaths from "vite-tsconfig-paths"; + +declare module "@remix-run/node" { + interface Future { + v3_singleFetch: true; + } +} + +export default defineConfig({ + plugins: [ + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + v3_singleFetch: true, + v3_lazyRouteDiscovery: true, + }, + }), + tsconfigPaths(), + ], +}); From 4ec78013193a1ea5c65661914eb90887d4d81c16 Mon Sep 17 00:00:00 2001 From: brandonkachen Date: Fri, 14 Feb 2025 02:46:48 -0800 Subject: [PATCH 21/34] feat: add Docker container support for codebuff --- .gitignore | 2 + utils/codebuff-docker/Dockerfile | 24 --- utils/codebuff-docker/README.md | 97 ---------- utils/codebuff-docker/entrypoint.sh | 40 ---- utils/codebuff-docker/knowledge.md | 110 ----------- utils/codebuff-docker/start-codebuff.sh | 140 -------------- utils/docker/Dockerfile | 31 ++++ utils/docker/README.md | 131 +++++++++++++ utils/docker/codebuff-wrapper.sh | 134 ++++++++++++++ utils/docker/entrypoint.sh | 96 ++++++++++ utils/docker/knowledge.md | 237 ++++++++++++++++++++++++ utils/docker/message-bridge.sh | 38 ++++ utils/docker/start-codebuff.sh | 163 ++++++++++++++++ 13 files changed, 832 insertions(+), 411 deletions(-) delete mode 100644 utils/codebuff-docker/Dockerfile delete mode 100644 utils/codebuff-docker/README.md delete mode 100644 utils/codebuff-docker/entrypoint.sh delete mode 100644 utils/codebuff-docker/knowledge.md delete mode 100755 utils/codebuff-docker/start-codebuff.sh create mode 100644 utils/docker/Dockerfile create mode 100644 utils/docker/README.md create mode 100755 utils/docker/codebuff-wrapper.sh create mode 100755 utils/docker/entrypoint.sh create mode 100644 utils/docker/knowledge.md create mode 100755 utils/docker/message-bridge.sh create mode 100755 utils/docker/start-codebuff.sh diff --git a/.gitignore b/.gitignore index e43b0f9..2bc2f1a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ +# ... existing content ... +**/comm/ .DS_Store diff --git a/utils/codebuff-docker/Dockerfile b/utils/codebuff-docker/Dockerfile deleted file mode 100644 index 672ee4b..0000000 --- a/utils/codebuff-docker/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM node:20-slim - -# Install necessary dependencies including Python and build tools -RUN apt-get update && \ - apt-get install -y \ - git \ - python3 \ - python-is-python3 \ - make \ - g++ \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Install codebuff globally -RUN npm install -g codebuff - -# Create a directory for mounting projects -WORKDIR /workspace - -# Create an entrypoint script -COPY entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] diff --git a/utils/codebuff-docker/README.md b/utils/codebuff-docker/README.md deleted file mode 100644 index 67f0d69..0000000 --- a/utils/codebuff-docker/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Codebuff Docker Container - -This Docker container provides a standardized environment for running codebuff on any local project directory. It handles native dependencies and provides consistent behavior across different host systems. - -## Quick Start - -Run the interactive setup script: - -```bash -./start-codebuff.sh -``` - -This script will: - -1. Check if Docker is installed -2. Build the Docker image if needed -3. Guide you through mounting your project directory -4. Create a persistent tmux session for your project - -## Manual Setup - -If you prefer to set things up manually: - -### Building the Image - -```bash -docker build -t codebuff . -``` - -### Running the Container - -Mount your project directory and run codebuff: - -```bash -docker run -it --rm \ - -e PROJECT_PATH=myproject \ - -v /path/to/parent/dir:/workspace \ - codebuff -``` - -Where: - -- `/path/to/parent/dir` is the parent directory containing your project -- `myproject` is the name of your project directory - -Example: - -```bash -# If your project is at /Users/me/projects/myapp -docker run -it --rm \ - -e PROJECT_PATH=myapp \ - -v /Users/me/projects:/workspace \ - codebuff -``` - -## Features - -- Automatic handling of native dependencies -- Support for both relative and absolute paths -- Interactive setup with path auto-completion -- Consistent behavior across platforms -- Safe read-only access to host files (works on copy) - -## Technical Details - -- Based on node:slim for minimal image size -- Includes essential build tools (python3, make, g++) -- Handles native module compilation automatically -- Uses tmux for session persistence -- Supports both interactive and automated usage - -## Path Handling - -The container supports both absolute and relative paths: - -- Host paths are mounted at /workspace -- Project paths are resolved relative to the mount point -- Paths are normalized to handle different formats -- Special case handling for current directory (".") - -## Troubleshooting - -### Windows Path Issues - -If you're on Windows, use the appropriate path format: - -- Git Bash: `/c/Users/YourName/projects` -- PowerShell: `C:/Users/YourName/projects` -- WSL: Use native Linux paths - -### Permission Issues - -If you encounter permission issues: - -1. Ensure write permissions on your project directory -2. On Linux, run Docker with sudo or add your user to the docker group - diff --git a/utils/codebuff-docker/entrypoint.sh b/utils/codebuff-docker/entrypoint.sh deleted file mode 100644 index 79ca518..0000000 --- a/utils/codebuff-docker/entrypoint.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# Check if a project path was provided -if [ -z "$PROJECT_PATH" ]; then - echo "Error: PROJECT_PATH environment variable not set" - echo "Usage: docker run -e PROJECT_PATH=/path/to/project -v /host/path:/workspace codebuff" - exit 1 -fi - -# Strip any leading slashes from PROJECT_PATH to make it relative -RELATIVE_PATH="${PROJECT_PATH#/}" - -# Debug output -echo "Original PROJECT_PATH: $PROJECT_PATH" -echo "Relative path: $RELATIVE_PATH" -echo "Workspace contents:" -ls -la /workspace - -# Check if the project directory exists -if [ ! -d "/workspace/$RELATIVE_PATH" ]; then - echo "Error: Project directory not found at /workspace/$RELATIVE_PATH" - echo "Make sure you mounted the correct directory and provided the right PROJECT_PATH" - exit 1 -fi - -# Create a working directory for this session -WORK_DIR="/tmp/codebuff_workspace/$RELATIVE_PATH" -mkdir -p "$(dirname "$WORK_DIR")" - -# Copy project files to working directory -echo "Copying project files to working directory..." -cp -r "/workspace/$RELATIVE_PATH" "$WORK_DIR" - -# Change to the working directory -cd "$WORK_DIR" - -echo "Checking for codebuff updates..." -npm update -g codebuff -echo "Starting codebuff..." -exec codebuff diff --git a/utils/codebuff-docker/knowledge.md b/utils/codebuff-docker/knowledge.md deleted file mode 100644 index e438653..0000000 --- a/utils/codebuff-docker/knowledge.md +++ /dev/null @@ -1,110 +0,0 @@ -# Docker Container Knowledge - -## Native Dependencies - -When containerizing Node.js applications with native dependencies: - -- Always include Python 3 and build tools (make, g++) -- Use `python-is-python3` package to ensure `python` command exists -- Clean up apt cache after installing dependencies -- Include these even if native deps are optional - better to have them ready -- Required for node-gyp and native module compilation: - - python3 (and python symlink) - - make - - g++ - - git (for npm packages from git) -- Clean up apt cache after installing to reduce image size -- Install build tools before npm install to avoid compilation errors - -## Container Best Practices - -- Use node:slim as base to minimize image size -- Clean up package manager cache after installing deps -- Set WORKDIR before COPY/RUN commands that use it -- Make entrypoint scripts executable in Dockerfile -- Never write to mounted volumes - copy to working directory instead -- Keep image names simple and context-aware -- Avoid redundant suffixes like '-docker' in image names -- Use descriptive but concise container and image names -- Order RUN commands by stability: - - System packages first (apt-get) - - Build tools second (python, make, g++) - - npm installs last -- This ordering maximizes Docker layer cache hits -- Cache apt-get lists cleanup in same RUN layer as install - -## Path Handling - -When mounting directories in Docker: -- Always use relative paths inside container -- Strip leading slashes from paths before concatenating -- Convert host paths to absolute before mounting -- When user provides absolute path, make it relative to mount point -- Handle both relative and absolute paths in bootstrap scripts -- Verify project paths are within mounted directory -- Clean up paths by removing double slashes and trailing slashes -- Add debug output in entrypoint scripts for path diagnostics -- Handle special case where project path is mount directory (".") -- Normalize paths in both bootstrap and entrypoint scripts -- Show explicit path resolution steps in debug output -- Remove leading slashes before any path concatenation -- For project paths, mount the parent directory and use the last component as PROJECT_PATH -- Support both interactive prompts and command-line arguments for automation -- Add debug output showing path resolution steps for easier troubleshooting -- Validate directory existence before proceeding -- Convert paths to absolute form for validation -- Use current directory as default when appropriate -- Show clear error messages for missing directories - -## Terminal UI Best Practices - -- Use `read -e` for path auto-completion in supported shells -- Show default values in gray using ANSI color codes -- Allow accepting defaults by pressing Enter -- Use colors consistently for different types of output: - - Gray for defaults/suggestions (including default options in Y/n prompts) - - Green for success/status - - Yellow for notes/warnings - - Red for errors -- Provide visual separation between sections with headers -- Show command previews before execution -- Support both interactive and automated usage through command-line args -- Show default values inline with prompt text -- Use parentheses around default values for clarity -- Keep prompt and input on same line -- Detect shell capabilities for better readline support -- Provide fallbacks for shells without readline -- Format yes/no prompts consistently with other prompts -- Show default option in gray: [Y/n] or [y/N] - -### Terminal Color Handling - -- Use tput when available for better terminal compatibility -- Provide ANSI color code fallbacks when tput is not available -- Always quote color variables in printf statements -- Use setaf for foreground colors (1=red, 2=green, 3=yellow, 8=gray) -- Use sgr0 to reset all attributes -- Redirect tput stderr to /dev/null to handle non-terminal cases -- Test color output in both terminal and non-terminal environments - -## Script Distribution - -- Prefer bash scripts over Node.js for setup tools -- Bash provides better cross-platform compatibility -- Avoid unnecessary dependencies on runtimes (Node, Python, etc.) -- Shell scripts work on most Unix-like systems out of the box -- Windows users typically have Git Bash or WSL available -- Keep terminal UI simple and compatible with basic shells -- Stick to standard Unix conventions for prompts and input - -## Session Management - -Avoid using tmux or other session managers in Docker when: -- The main process is already interactive -- The container is designed to run a single process -- Session management would create recursive execution - -Instead: -- Run the interactive process directly -- Use Docker's built-in TTY and interactive mode (-it flags) -- Let Docker handle the container lifecycle \ No newline at end of file diff --git a/utils/codebuff-docker/start-codebuff.sh b/utils/codebuff-docker/start-codebuff.sh deleted file mode 100755 index 9dfa681..0000000 --- a/utils/codebuff-docker/start-codebuff.sh +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env bash -set -e - -# ------------------------------------------------------------------------------ -# start-codebuff.sh -# A helper script to guide you through setting up and running Codebuff in Docker -# ------------------------------------------------------------------------------ - -# ANSI color codes - using simpler codes for better compatibility -GRAY="$(tput setaf 8 2>/dev/null || echo '\033[90m')" # Fallback to 90m if tput not available -RESET="$(tput sgr0 2>/dev/null || echo '\033[0m')" -GREEN="$(tput setaf 2 2>/dev/null || echo '\033[32m')" -YELLOW="$(tput setaf 3 2>/dev/null || echo '\033[33m')" -RED="$(tput setaf 1 2>/dev/null || echo '\033[31m')" - -# ------------------------- Check if Docker Installed --------------------------- -if ! command -v docker &> /dev/null -then - echo "Docker is not installed or not in your PATH." - echo "Visit Docker installation docs for more info:" - echo " Linux: https://docs.docker.com/engine/install/" - echo " macOS: https://docs.docker.com/desktop/install/mac-install/" - echo " Windows: https://docs.docker.com/desktop/install/windows-install/" - exit 1 -fi - -# ------------------------- Prompt for Docker Build ----------------------------- -echo "Checking if the 'codebuff' image exists..." -IMAGE_EXISTS=$(docker images --format "{{.Repository}}" | grep "^codebuff$" || true) - -if [[ -z "$IMAGE_EXISTS" ]]; then - printf "No 'codebuff' image found. Would you like to build it now? [%sY%s/n] " "${GRAY}" "${RESET}" - read -r BUILD_CHOICE - if [[ -z "$BUILD_CHOICE" || "$BUILD_CHOICE" =~ ^[Yy]$ ]]; then - echo "Building Docker image 'codebuff' (this may take a while)..." - docker build -t codebuff . - echo "Docker image 'codebuff' built successfully." - else - echo "Cannot proceed without 'codebuff' image. Exiting." - exit 1 - fi -else - echo "Docker image 'codebuff' already exists." -fi - -# ------------------------- Get Project Path ------------------------------------ -DEFAULT_PATH="$(pwd)" -printf "Enter the project path (%s%s%s): " "${GRAY}" "${DEFAULT_PATH}" "${RESET}" -read -r SELECTED_PROJECT_PATH - -if [ -z "$SELECTED_PROJECT_PATH" ]; then - SELECTED_PROJECT_PATH="$DEFAULT_PATH" -fi - -# Validate that the selected path exists -if [ ! -d "$SELECTED_PROJECT_PATH" ]; then - printf "%sError: Directory does not exist: %s%s\n" "${RED}" "$SELECTED_PROJECT_PATH" "${RESET}" - exit 1 -fi - -# Convert to absolute path -SELECTED_PROJECT_PATH=$(cd "$SELECTED_PROJECT_PATH" && pwd) - -# ------------------------- Get Host Base Directory ----------------------------- -# This is the path you want to mount on the host side. By default, use parent of project dir -HOST_MOUNT_DIR=$(dirname "$SELECTED_PROJECT_PATH") -printf "Enter the host path (%s%s%s): " "${GRAY}" "${HOST_MOUNT_DIR}" "${RESET}" -read -r NEW_MOUNT - -if [ -n "$NEW_MOUNT" ]; then - # Validate that the new mount directory exists - if [ ! -d "$NEW_MOUNT" ]; then - printf "%sError: Directory does not exist: %s%s\n" "${RED}" "$NEW_MOUNT" "${RESET}" - exit 1 - fi - HOST_MOUNT_DIR="$NEW_MOUNT" -fi - -# Convert to absolute path and normalize -HOST_MOUNT_DIR=$(cd "$HOST_MOUNT_DIR" && pwd) - -# Get the relative path for PROJECT_PATH -if [[ "$SELECTED_PROJECT_PATH" = /* ]]; then - # If absolute path provided, make it relative to HOST_MOUNT_DIR - if [[ "$SELECTED_PROJECT_PATH" == "$HOST_MOUNT_DIR"* ]]; then - # Path is under HOST_MOUNT_DIR, so we can make it relative - RELATIVE_PATH="${SELECTED_PROJECT_PATH#$HOST_MOUNT_DIR/}" - # If empty after stripping, use "." for current directory - if [ -z "$RELATIVE_PATH" ]; then - RELATIVE_PATH="." - fi - else - printf "%sError: Selected project path must be within the mounted directory\n" - echo "Project path: $SELECTED_PROJECT_PATH" - echo "Mount directory: $HOST_MOUNT_DIR%s\n" "${RESET}" - exit 1 - fi -else - # For relative paths, just use as-is - RELATIVE_PATH="$SELECTED_PROJECT_PATH" -fi - -# Remove any double slashes, trailing slashes, and leading slashes -RELATIVE_PATH=$(echo "$RELATIVE_PATH" | sed 's#^/##' | sed 's#/\+#/#g' | sed 's#/$##') - -# Debug output -echo -printf "%sPath resolution:%s\n" "${GREEN}" "${RESET}" -echo " Host mount dir: $HOST_MOUNT_DIR" -echo " Selected path: $SELECTED_PROJECT_PATH" -echo " Resolved to: $RELATIVE_PATH" -echo - -# ------------------------- Show Command & Prompt to Run ----------------------- -DOCKER_CMD="docker run -it --rm -e PROJECT_PATH=$RELATIVE_PATH -v \"$HOST_MOUNT_DIR:/workspace\" codebuff" - -printf "%sHere's the Docker command that will be run:%s\n" "${GREEN}" "${RESET}" -echo -echo " $DOCKER_CMD" -echo -printf "%sNotes:%s\n" "${YELLOW}" "${RESET}" -echo " • '-it' runs Docker interactively with a TTY so you can see output." -echo " • '--rm' removes the container after exit." -echo " • '-e PROJECT_PATH=...' sets the folder name to open (within /workspace)." -echo " • '-v \"$HOST_MOUNT_DIR:/workspace\"' mounts your host project directory at /workspace." -echo - -printf "Would you like to run this command now? [%sY%s/n] " "${GRAY}" "${RESET}" -read -r RUN_CHOICE - -if [[ -z "$RUN_CHOICE" || "$RUN_CHOICE" =~ ^[Yy]$ ]]; then - echo "Starting Codebuff in Docker..." - echo - eval "$DOCKER_CMD" -else - echo "You can run this command later by copying and pasting it." - echo "Remember to replace $RELATIVE_PATH with your actual project folder name if different." -fi - -exit 0 \ No newline at end of file diff --git a/utils/docker/Dockerfile b/utils/docker/Dockerfile new file mode 100644 index 0000000..60efe7a --- /dev/null +++ b/utils/docker/Dockerfile @@ -0,0 +1,31 @@ +FROM node:20-slim + +# Install required packages +RUN apt-get update && \ + apt-get install -y \ + git \ + python3 \ + make \ + g++ \ + procps \ + inotify-tools \ + npm \ + build-essential \ + bsdutils \ + expect \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install/Update codebuff globally and verify installation +RUN npm install -g codebuff + +# Copy scripts +COPY codebuff-wrapper.sh /codebuff-wrapper.sh +COPY entrypoint.sh /entrypoint.sh +COPY message-bridge.sh /message-bridge.sh + +# Make scripts executable +RUN chmod +x /codebuff-wrapper.sh /entrypoint.sh /message-bridge.sh + +# Set entrypoint +ENTRYPOINT ["/entrypoint.sh"] diff --git a/utils/docker/README.md b/utils/docker/README.md new file mode 100644 index 0000000..46ffbcb --- /dev/null +++ b/utils/docker/README.md @@ -0,0 +1,131 @@ +# Codebuff Docker Container + +This Docker container provides a standardized environment for running codebuff on any local project directory. It handles native dependencies and provides consistent behavior across different host systems. + +## Quick Start + +From the project root directory: + +```bash +./utils/docker/start-codebuff.sh [optional-project-path] +``` + +This script will: + +1. Check if Docker is installed +2. Build the Docker image if needed +3. Set up communication channels between host and container +4. Mount your project directory and credentials +5. Start codebuff in an isolated environment + +## Architecture + +The system consists of several key components: + +### 1. Container Setup (`Dockerfile`) +- Based on node:20-slim for minimal size +- Includes essential build tools and dependencies +- Pre-installs codebuff globally +- Sets up communication scripts + +### 2. Entry Point (`entrypoint.sh`) +- Validates environment variables and paths +- Creates communication directory structure +- Sets up working directory with project files +- Handles npm dependencies +- Copies credentials from host +- Launches the codebuff wrapper + +### 3. Communication Bridge +The system uses a bidirectional communication system between host and container: + +- `message-bridge.sh`: Handles host-side communication +- `codebuff-wrapper.sh`: Manages container-side interaction using expect +- Communication files: + - `messages.txt`: Commands from host to container + - `responses.txt`: Output from container to host + +### 4. Project Management +- Creates isolated workspace in container +- Preserves original files in mounted volume +- Supports npm package installation +- Handles credentials via ~/.config/manicode mount + +## Usage + +### Basic Usage +```bash +./utils/docker/start-codebuff.sh +``` + +When prompted, enter your project path or press Enter to use current directory. + +### Advanced Usage +```bash +./utils/docker/start-codebuff.sh /path/to/your/project +``` + +### Environment Variables +- `DEBUG`: Set to true for verbose logging and automatic container cleanup +- `PROJECT_PATH`: Project directory name (set automatically) +- `PROJECT_NAME`: Project name for prompt (set automatically) + +## Directory Structure + +The container expects this structure: + +``` +/workspace/ # Mount point for host directory + └── your-project/ # Your project files + └── .codebuff/ # Communication directory + └── comm/ # Contains messages.txt and responses.txt +``` + +## Troubleshooting + +### Common Issues + +1. **Permission Errors** + - Ensure write permissions on project directory + - Check if .codebuff/comm directory exists and is writable + - Verify Docker has necessary permissions + +2. **Communication Issues** + - Check if comm files exist and are writable + - Verify container is running (`docker ps`) + - Check container logs (`docker logs `) + +3. **Path Issues** + - Use absolute paths when possible + - Verify project directory exists + - Check for proper directory structure + +### Windows Users +- Use appropriate path format: + - Git Bash: `/c/Users/YourName/projects` + - PowerShell: `C:/Users/YourName/projects` + - WSL: Use native Linux paths + +## Security Notes + +- Container runs with limited privileges +- Credentials are mounted read-only +- Project files are copied to isolated workspace +- Communication channels are local to project directory + +## Development + +To modify the container: + +1. Update Dockerfile if adding dependencies +2. Modify communication scripts as needed +3. Test with DEBUG=true for verbose logging +4. Rebuild image after changes + +## Technical Details + +- Uses expect for reliable terminal interaction +- Implements file-based communication protocol +- Supports credential persistence +- Handles npm package management +- Provides isolated workspace per session diff --git a/utils/docker/codebuff-wrapper.sh b/utils/docker/codebuff-wrapper.sh new file mode 100755 index 0000000..e4d3528 --- /dev/null +++ b/utils/docker/codebuff-wrapper.sh @@ -0,0 +1,134 @@ +#!/usr/bin/expect -f + +# Version 1.0.1 - Testing build update +# Log to stderr +proc log {msg} { + puts stderr "\[WRAPPER\] \[$msg\]" +} + +proc debug {msg} { + puts stderr "\[WRAPPER DEBUG\] \[$msg\]" +} + +proc strip_ansi {text} { + # Strip ANSI escape sequences + regsub -all {\x1b\[[0-9;]*[mGJK]} $text {} text + return $text +} + +proc write_response {line} { + if {![info exists ::env(PROJECT_PATH)]} { + log "ERROR: PROJECT_PATH environment variable not set" + exit 1 + } + + set project_path $::env(PROJECT_PATH) + set comm_dir "/workspace/$project_path/.codebuff/comm" + debug "Writing response to $comm_dir/responses.txt: $line" + if [catch { + set f [open "$comm_dir/responses.txt" "a"] + puts $f $line + close $f + debug "Successfully wrote response" + } err] { + log "Error writing response: $err" + } +} + +log "Starting codebuff wrapper..." + +# Verify required environment variables +if {![info exists ::env(PROJECT_PATH)]} { + log "ERROR: PROJECT_PATH environment variable not set" + exit 1 +} +if {![info exists ::env(PROJECT_NAME)]} { + log "ERROR: PROJECT_NAME environment variable not set" + exit 1 +} + +set project_name $::env(PROJECT_NAME) +set project_path $::env(PROJECT_PATH) +debug "Project name: $project_name" +debug "Project path: $project_path" +debug "Comm dir: /workspace/$project_path/.codebuff/comm" + +# Always enable debugging +exp_internal 1 +log_user 1 + +# Signal ready before starting codebuff +write_response "CONTAINER READY" + +# Start codebuff +spawn codebuff +debug "Spawned codebuff process" + +# Monitor messages.txt and send input +set timeout -1 +while {1} { + set messages_file "/workspace/$project_path/.codebuff/comm/messages.txt" + debug "Checking messages file: $messages_file" + + if {[file exists $messages_file]} { + debug "Found messages.txt file" + # Wait for a modification event + debug "Running inotifywait on $messages_file" + set result [catch {exec inotifywait -q -e modify $messages_file} err] + if {$result != 0} { + debug "inotifywait error: $err" + sleep 0.1 + continue + } + debug "Got inotifywait event" + + if [catch { + set f [open $messages_file r] + set message [read $f] + close $f + debug "Read message content: '$message'" + + if {$message != ""} { + debug "Sending message to codebuff" + send "$message" + sleep 1 + send "\r" + debug "Message sent" + + # Clear the message file after sending + debug "Clearing message file..." + if [catch { + set f [open $messages_file w] + close $f + debug "Message file cleared" + } err] { + log "Error clearing message file: $err" + } + } else { + debug "Message was empty" + } + } err] { + log "Error processing message: $err" + } + } else { + debug "Messages file does not exist" + } + + # Check for output from codebuff + expect { + -re "(.+)\r\n" { + debug "Got output: $expect_out(1,string)" + write_response $expect_out(1,string) + exp_continue + } + "$project_name > " { + debug "Got prompt" + write_response "$project_name > " + } + timeout { + # No output, continue checking messages + } + } + + sleep 0.1 +} diff --git a/utils/docker/entrypoint.sh b/utils/docker/entrypoint.sh new file mode 100755 index 0000000..ce1d534 --- /dev/null +++ b/utils/docker/entrypoint.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Enable error handling +set -e + +# Always enable command printing for debugging +set -x + +# Add timestamp to logs +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" +} + +debug() { + log "DEBUG: $*" +} + +error() { + log "ERROR: $*" + exit 1 +} + +# Check if a project path was provided +if [ -z "$PROJECT_PATH" ]; then + error "PROJECT_PATH environment variable is required" +fi + +# Strip any leading slashes from PROJECT_PATH to make it relative +RELATIVE_PATH="${PROJECT_PATH#/}" + +# Set up communication directory +COMM_DIR="/workspace/$RELATIVE_PATH/.codebuff/comm" +debug "Setting up comm directory at: $COMM_DIR" +mkdir -p "$COMM_DIR" || error "Failed to create $COMM_DIR directory" +chmod 777 "$COMM_DIR" || error "Failed to set permissions on $COMM_DIR" + +# Create communication files with proper permissions +touch "$COMM_DIR/messages.txt" "$COMM_DIR/responses.txt" || error "Failed to create communication files" +chmod 666 "$COMM_DIR/messages.txt" "$COMM_DIR/responses.txt" || error "Failed to set permissions on communication files" + +# Create a working directory for this session +WORK_DIR="/tmp/codebuff_workspace/$RELATIVE_PATH" +mkdir -p "$WORK_DIR" || error "Failed to create working directory" + +# Copy project files to working directory with error handling +debug "Copying project files to working directory..." +cd "/workspace/$RELATIVE_PATH" || error "Failed to change to source directory" + +# Copy files individually +for file in .gitignore README.md eslint.config.js index.html knowledge.md package.json pnpm-lock.yaml tsconfig.app.json tsconfig.json tsconfig.node.json vite.config.ts; do + if [ -f "$file" ]; then + debug "Copying file: $file" + cp "$file" "$WORK_DIR/" || log "Failed to copy $file" + fi +done + +# Copy directories individually +for dir in public src; do + if [ -d "$dir" ]; then + debug "Copying directory: $dir" + cp -r "$dir" "$WORK_DIR/" || log "Failed to copy $dir" + fi +done + +# Change to the working directory +cd "$WORK_DIR" || error "Failed to change to working directory" + +# Install dependencies if package.json exists +if [ -f "package.json" ]; then + debug "Setting up npm..." + source /root/.bashrc + log "Installing dependencies..." + npm install --silent || error "Failed to install dependencies" +fi + +# Set up credentials directory in container's home directory +CREDS_DIR="$HOME/.config/manicode" +mkdir -p "$CREDS_DIR" || error "Failed to create credentials directory" +if [ -f "/workspace/.config/manicode/credentials.json" ]; then + if ! cp "/workspace/.config/manicode/credentials.json" "$CREDS_DIR/credentials.json"; then + debug "Warning: Failed to copy credentials file, continuing without credentials" + else + debug "Credentials copied from host to container's home directory" + fi +fi + +# Verify codebuff is available and in PATH +PATH="/usr/local/bin:$PATH" +export PATH + +which codebuff || error "codebuff command not found in PATH" +debug "Found codebuff at: $(which codebuff)" + +# Start codebuff wrapper +log "Starting codebuff with communication layer..." +exec /codebuff-wrapper.sh diff --git a/utils/docker/knowledge.md b/utils/docker/knowledge.md new file mode 100644 index 0000000..72bbaf7 --- /dev/null +++ b/utils/docker/knowledge.md @@ -0,0 +1,237 @@ +# Codebuff Docker Container Knowledge + +## Docker Image Distribution +- Build images locally rather than distributing via registry +- Benefits: + - Self-contained, no external dependencies + - Users can inspect/modify Dockerfile + - Works offline after first build + - Automatically stays in sync with code + - No registry maintenance needed + +## Communication Protocol +- Uses `.codebuff/comm` directory in project root +- Files: + - `messages.txt`: Commands from host to container + - `responses.txt`: Container output and status +- Permissions: 666 to allow container read/write + +## Container Lifecycle +- Build image if: + 1. Image doesn't exist + 2. Dockerfile modified since last build +- Container starts with: + 1. Project directory mount + 2. Credentials mount + 3. Communication directory mount +- Waits for "CONTAINER READY" signal before proceeding + +## Container Setup +- Base image: node:20-slim +- Additional packages: git, python3, make, g++, procps +- Working directory: /workspace +- Project files copied to /tmp/codebuff_workspace/[PROJECT_PATH] +- Container must run with --privileged flag for filesystem access + +## Communication System +Two approaches available: +1. Named Pipes (FIFO) + - More traditional but can be tricky with blocking + - Requires careful handling of read/write operations + - Better for streaming data + +2. File-Based (Current Implementation) + - More reliable for debugging + - Uses messages.txt for host→container + - Uses responses.txt for container→host + - Monitor file size changes to detect new messages + - Keep only latest message by overwriting instead of appending + - Use inotifywait for efficient file change detection when available + - Fall back to modification time polling if inotifywait not available + - Append-only operation (>>) for atomic writes + - Set 666 permissions on shared files + +### Test Scripts +- test-comm.sh: Continuous bidirectional testing +- message-bridge.sh: Interactive messaging interface +- test-message.sh: Single message testing utility + +## Named Pipe Communication +When using named pipes (FIFOs) for bidirectional communication: +- Create pipes before starting communication +- Handle pipe reads/writes in background to avoid blocking +- Use traps to clean up background processes +- Keep pipe operations simple and robust +- Prefer background writes with & to avoid blocking +- Use sleep between operations to prevent busy waiting +- Set appropriate permissions (666) for pipes +- Clean up pipes on exit +- Docker mounts preserve pipe functionality across container boundary +- Pipe redirection must happen inside container context when using docker exec +- Test pipe communication manually before running complex scripts + +## File-Based Communication +For reliable container communication: +- Use regular files instead of pipes for simpler debugging +- Keep only latest message by overwriting instead of appending +- Use inotifywait for efficient file change detection when available +- Fall back to modification time polling if inotifywait not available +- Set 666 permissions on shared files +- Mount comm directory separately from workspace + +## Best Practices +- Always use exec in entrypoint.sh to replace shell process +- Log extensively during development +- Test communication before adding application logic +- Clean up resources on container exit +- Use separate volume mounts for code vs communication +- Label all logs with source (HOST/CONTAINER) and timestamp +- Use background writes to avoid blocking +- Monitor file sizes for changes instead of continuous reads +- Keep communication files outside of project directory (in comm/) + +## Container Best Practices + +- Use node:slim as base to minimize image size +- Clean up package manager cache after installing deps +- Set WORKDIR before COPY/RUN commands that use it +- Make entrypoint scripts executable in Dockerfile +- Never write to mounted volumes - copy to working directory instead +- Keep image names simple and context-aware +- Avoid redundant suffixes like '-docker' in image names +- Use descriptive but concise container and image names +- Order RUN commands by stability: + - System packages first (apt-get) + - Build tools second (python, make, g++) + - npm installs last +- This ordering maximizes Docker layer cache hits +- Cache apt-get lists cleanup in same RUN layer as install + +## Path Handling + +When mounting directories in Docker: +- Always use relative paths inside container +- Strip leading slashes from paths before concatenating +- Convert host paths to absolute before mounting +- When user provides absolute path, make it relative to mount point +- Handle both relative and absolute paths in bootstrap scripts +- Verify project paths are within mounted directory +- Clean up paths by removing double slashes and trailing slashes +- Add debug output in entrypoint scripts for path diagnostics +- Handle special case where project path is mount directory (".") +- Normalize paths in both bootstrap and entrypoint scripts +- Show explicit path resolution steps in debug output +- Remove leading slashes before any path concatenation +- For project paths, mount the parent directory and use the last component as PROJECT_PATH +- Support both interactive prompts and command-line arguments for automation +- Add debug output showing path resolution steps for easier troubleshooting +- Validate directory existence before proceeding +- Convert paths to absolute form for validation +- Use current directory as default when appropriate +- Show clear error messages for missing directories + +## Terminal UI Best Practices + +- Use `read -e` for path auto-completion in supported shells +- Show default values in gray using ANSI color codes +- Allow accepting defaults by pressing Enter +- Use colors consistently for different types of output: + - Gray for defaults/suggestions (including default options in Y/n prompts) + - Green for success/status + - Yellow for notes/warnings + - Red for errors +- Provide visual separation between sections with headers +- Show command previews before execution +- Support both interactive and automated usage through command-line args +- Show default values inline with prompt text +- Use parentheses around default values for clarity +- Keep prompt and input on same line +- Detect shell capabilities for better readline support +- Provide fallbacks for shells without readline +- Format yes/no prompts consistently with other prompts +- Show default option in gray: [Y/n] or [y/N] + +### Terminal Color Handling + +- Use tput when available for better terminal compatibility +- Provide ANSI color code fallbacks when tput is not available +- Always quote color variables in printf statements +- Use setaf for foreground colors (1=red, 2=green, 3=yellow, 8=gray) +- Use sgr0 to reset all attributes +- Redirect tput stderr to /dev/null to handle non-terminal cases +- Test color output in both terminal and non-terminal environments + +## Script Distribution + +- Prefer bash scripts over Node.js for setup tools +- Bash provides better cross-platform compatibility +- Avoid unnecessary dependencies on runtimes (Node, Python, etc.) +- Shell scripts work on most Unix-like systems out of the box +- Windows users typically have Git Bash or WSL available +- Keep terminal UI simple and compatible with basic shells +- Stick to standard Unix conventions for prompts and input + +## Session Management + +Avoid using tmux or other session managers in Docker when: +- The main process is already interactive +- The container is designed to run a single process +- Session management would create recursive execution + +Instead: +- Run the interactive process directly +- Use Docker's built-in TTY and interactive mode (-it flags) +- Let Docker handle the container lifecycle + +## Terminal Handling +- Use `script` command with `-qf` flags for reliable PTY handling +- Install `bsdutils` package for script command +- Create PTY file with 666 permissions +- Use `tail -f` to continuously read PTY output +- Write to `/dev/pts/0` for PTY input +- When sending input to Node.js readline: + - Add delay (0.5-1s) between message and Enter key + - Send \r for Enter key + - Node.js needs time to process input before receiving Enter +- Use expect's exp_internal 1 for debugging terminal interactions + +## File-Based Communication +- Use regular files instead of pipes for simpler debugging +- Keep only latest message by overwriting instead of appending +- Use inotifywait for efficient file change detection when available +- Fall back to modification time polling if inotifywait not available +- Set 666 permissions on shared files +- Mount comm directory separately from workspace + +## Error Handling +- Add cleanup trap for process termination +- Check file permissions on startup +- Verify required directories exist +- Kill background processes on exit +- Handle missing files gracefully + +## Process Management +- Use background processes with & for async operations +- Store PIDs for cleanup +- Wait for main process to exit +- Use exec to replace shell in entrypoint +- Signal container readiness through response file + +## Package Requirements +- inotify-tools: For file change monitoring +- bsdutils: For script command and PTY handling +- procps: For process management +- util-linux: Alternative for script command + +## Testing +- Use test mode for verifying communication +- Echo server for basic verification +- Timeout handling for stuck processes +- Clear error messages for debugging + +## Interactive Program Handling +- Use expect for interactive program automation +- Wait for specific prompts before sending input +- Clear input files after sending to prevent duplicate sends +- Use inotifywait to detect file changes efficiently +- Flush output buffers after sending commands \ No newline at end of file diff --git a/utils/docker/message-bridge.sh b/utils/docker/message-bridge.sh new file mode 100755 index 0000000..e005018 --- /dev/null +++ b/utils/docker/message-bridge.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -e + +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" +} + +debug() { + if [ "${DEBUG:-false}" = "true" ]; then + log "DEBUG: $*" + fi +} + +cleanup() { + log "Cleaning up..." + exit 0 +} +trap cleanup SIGINT SIGTERM EXIT + +# Get the project directory from the command line argument +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +PROJECT_DIR="$1" +COMM_DIR="$PROJECT_DIR/.codebuff/comm" +debug "Using comm directory: $COMM_DIR" + +# Wait for comm directory and files to exist +log "Waiting for comm directory and files..." +while [ ! -f "$COMM_DIR/responses.txt" ]; do + sleep 0.1 +done + +# Main loop - tail the responses file +log "Starting to tail responses.txt..." +tail -f "$COMM_DIR/responses.txt" diff --git a/utils/docker/start-codebuff.sh b/utils/docker/start-codebuff.sh new file mode 100755 index 0000000..3f2c006 --- /dev/null +++ b/utils/docker/start-codebuff.sh @@ -0,0 +1,163 @@ +#!/bin/bash +set -e + +# ANSI color codes - using simpler codes for better compatibility +GRAY="$(tput setaf 8 2>/dev/null || echo '\033[90m')" # Fallback to 90m if tput not available +RESET="$(tput sgr0 2>/dev/null || echo '\033[0m')" +GREEN="$(tput setaf 2 2>/dev/null || echo '\033[32m')" +YELLOW="$(tput setaf 3 2>/dev/null || echo '\033[33m')" +RED="$(tput setaf 1 2>/dev/null || echo '\033[31m')" + +# Add timestamp to logs +log() { + echo "[HOST] [$(date '+%Y-%m-%d %H:%M:%S')] $*" +} + +debug() { + if [ "${DEBUG}" = true ]; then + echo "[HOST] [DEBUG] [$(date '+%Y-%m-%d %H:%M:%S')] $*" + fi +} + +error() { + echo "[HOST] [ERROR] [$(date '+%Y-%m-%d %H:%M:%S')] $*" +} + +cleanup() { + log "Cleaning up..." + if [ "${DEBUG}" = true ]; then + debug "Stopping container: $CONTAINER_ID" + docker stop "$CONTAINER_ID" >/dev/null 2>&1 || true + debug "Removing container: $CONTAINER_ID" + docker rm "$CONTAINER_ID" >/dev/null 2>&1 || true + fi + exit 0 +} +trap cleanup SIGINT SIGTERM EXIT + +# Get the directory where this script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Check if Docker is installed +if ! command -v docker &> /dev/null; then + error "Docker is not installed. Please install Docker first." + exit 1 +fi + +# Build or rebuild the Docker image +log "Checking Docker image..." +if ! docker images codebuff --format "{{.ID}}" | grep -q .; then + log "Building Docker image for the first time..." + docker build -t codebuff "$SCRIPT_DIR" || { error "Failed to build Docker image"; exit 1; } +else + # Always rebuild if any of the scripts have been modified + DOCKERFILE_MTIME=$(stat -f %m "$SCRIPT_DIR/Dockerfile") + WRAPPER_MTIME=$(stat -f %m "$SCRIPT_DIR/codebuff-wrapper.sh") + ENTRYPOINT_MTIME=$(stat -f %m "$SCRIPT_DIR/entrypoint.sh") + BRIDGE_MTIME=$(stat -f %m "$SCRIPT_DIR/message-bridge.sh") + + # Get the most recent modification time + LATEST_MTIME=$DOCKERFILE_MTIME + for t in $WRAPPER_MTIME $ENTRYPOINT_MTIME $BRIDGE_MTIME; do + if [ $t -gt $LATEST_MTIME ]; then + LATEST_MTIME=$t + fi + done + + debug "Latest modification time: $LATEST_MTIME" + debug "Raw modification time: $(stat -f %Sm "$SCRIPT_DIR/Dockerfile")" + + # Always rebuild for now - safer while we're actively developing + log "Scripts may have been modified. Rebuilding image..." + docker build -t codebuff "$SCRIPT_DIR" || { error "Failed to rebuild Docker image"; exit 1; } +fi + +# ------------------------- Get Project Path ------------------------------------ +DEFAULT_PATH="$(pwd)" +if [ -n "$1" ]; then + SELECTED_PROJECT_PATH="$1" +else + printf "Enter the project path (%s%s%s): " "${GRAY}" "${DEFAULT_PATH}" "${RESET}" + read -r SELECTED_PROJECT_PATH + SELECTED_PROJECT_PATH=${SELECTED_PROJECT_PATH:-$DEFAULT_PATH} +fi + +# Convert to absolute path +SELECTED_PROJECT_PATH=$(cd "$SELECTED_PROJECT_PATH" && pwd) + +# ------------------------- Get Host Base Directory ----------------------------- +# Automatically determine host mount dir as parent of project dir +HOST_MOUNT_DIR=$(dirname "$SELECTED_PROJECT_PATH") +RELATIVE_PATH=$(basename "$SELECTED_PROJECT_PATH") + +# Extract project name from path +PROJECT_NAME="$RELATIVE_PATH" + +# Debug output +echo +debug "Host mount dir: $HOST_MOUNT_DIR" +debug "Selected path: $SELECTED_PROJECT_PATH" +debug "Resolved to: $RELATIVE_PATH" +debug "Project name: $PROJECT_NAME" +echo + +# Create comm directory inside the project directory +debug "Setting up communication directory..." +COMM_DIR="$SELECTED_PROJECT_PATH/.codebuff/comm" +mkdir -p "$COMM_DIR" +touch "$COMM_DIR/messages.txt" "$COMM_DIR/responses.txt" +chmod 666 "$COMM_DIR/messages.txt" "$COMM_DIR/responses.txt" + +# Start container in background +log "Starting container..." +CONTAINER_ID=$(docker run -d --privileged \ + -e "PROJECT_PATH=$RELATIVE_PATH" \ + -e "PROJECT_NAME=$PROJECT_NAME" \ + -e "DEBUG=${DEBUG:-false}" \ + -v "$HOME/.config/manicode:/workspace/.config/manicode" \ + -v "$HOST_MOUNT_DIR:/workspace" \ + codebuff) + +echo "${GREEN}Started container with ID: $CONTAINER_ID${RESET}" +debug "Container mounts:" +docker inspect "$CONTAINER_ID" --format='{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}' + +# Wait for container to be ready with better error handling +log "Checking container status..." +timeout=300 +start_time=$(date +%s) +while true; do + # Check if container is still running using full container ID + if ! docker ps --no-trunc -q | grep -q "$CONTAINER_ID"; then + error "Container stopped unexpectedly" + log "Container logs:" + docker logs "$CONTAINER_ID" + echo + log "Exit code:" + docker inspect "$CONTAINER_ID" --format='{{.State.ExitCode}}' + exit 1 + fi + + # Check for ready signal + if [ -s "$COMM_DIR/responses.txt" ] && grep -q "CONTAINER READY" "$COMM_DIR/responses.txt"; then + log "Container started successfully" + # Clear responses.txt after container is ready + echo > "$COMM_DIR/responses.txt" + break + fi + + # Check timeout + current_time=$(date +%s) + if [ $((current_time - start_time)) -gt "$timeout" ]; then + error "Timeout waiting for container to start" + log "Container logs:" + docker logs "$CONTAINER_ID" + docker stop "$CONTAINER_ID" + exit 1 + fi + sleep 1 +done + +# Start message bridge +debug "Starting message bridge..." +exec "$SCRIPT_DIR/message-bridge.sh" "$SELECTED_PROJECT_PATH" From 84b5d31ca53c3ac23c669d6d3c0a5791ba336ece Mon Sep 17 00:00:00 2001 From: James Grugett Date: Mon, 17 Feb 2025 14:25:41 -0800 Subject: [PATCH 22/34] Add calendar-on-air to showcase --- .gitmodules | 3 +++ showcase/calendar-on-air | 1 + 2 files changed, 4 insertions(+) create mode 160000 showcase/calendar-on-air diff --git a/.gitmodules b/.gitmodules index 87ac680..21f5fcc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "showcase/codebuff-tricks"] path = showcase/codebuff-tricks url = https://github.com/narthur/codebuff-tricks +[submodule "showcase/calendar-on-air"] + path = showcase/calendar-on-air + url = https://gist.github.com/dhunten/7f88654f3972bfe0fc6d70a1b5fa024a diff --git a/showcase/calendar-on-air b/showcase/calendar-on-air new file mode 160000 index 0000000..b2e2b25 --- /dev/null +++ b/showcase/calendar-on-air @@ -0,0 +1 @@ +Subproject commit b2e2b25e788ca7a50c42f3a5a991f4b860e37306 From 077ad0d17a965bfcf5ce133527dc968502a86296 Mon Sep 17 00:00:00 2001 From: psymed Date: Wed, 19 Feb 2025 17:33:38 +0200 Subject: [PATCH 23/34] feat: Add vending-machine showcase as submodule --- .gitmodules | 3 +++ showcase/vending-machine | 1 + 2 files changed, 4 insertions(+) create mode 160000 showcase/vending-machine diff --git a/.gitmodules b/.gitmodules index 21f5fcc..b05c2e0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "showcase/calendar-on-air"] path = showcase/calendar-on-air url = https://gist.github.com/dhunten/7f88654f3972bfe0fc6d70a1b5fa024a +[submodule "showcase/vending-machine"] + path = showcase/vending-machine + url = https://github.com/ShAIWhisperer/vending-machine.git diff --git a/showcase/vending-machine b/showcase/vending-machine new file mode 160000 index 0000000..fb58bec --- /dev/null +++ b/showcase/vending-machine @@ -0,0 +1 @@ +Subproject commit fb58bec04872d3b9a7ef67191a77842db42ba849 From 9df25a5613938d0c7174cc4ccd93aeb2fe51edb3 Mon Sep 17 00:00:00 2001 From: psymed Date: Wed, 19 Feb 2025 17:39:02 +0200 Subject: [PATCH 24/34] docs: Add vending-machine project to showcase README --- showcase/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/showcase/README.md b/showcase/README.md index 42ed18a..fdb5c56 100644 --- a/showcase/README.md +++ b/showcase/README.md @@ -13,6 +13,13 @@ Community showcase of projects built by Codebuff - Fishies - An aquarium with various fishies - Code Analysis - A project by [Lachlan Gray](https://github.com/LachlanGray) to show interesting stats on any Github repo +## Vending Machine +A showcase project demonstrating a modern vending machine interface with: +- Interactive UI with animations +- Product selection and purchase flow +- Testing implementation +- [Link to repository](https://github.com/ShAIWhisperer/vending-machine) + ## Cloning This repository contains submodules. To clone including all showcase projects, use: From 0780698016ee15bd550cc330bf922bc7a4970bd9 Mon Sep 17 00:00:00 2001 From: psymed Date: Wed, 19 Feb 2025 17:51:52 +0200 Subject: [PATCH 25/34] chore: Update vending-machine submodule to latest version --- showcase/vending-machine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/showcase/vending-machine b/showcase/vending-machine index fb58bec..3584d8b 160000 --- a/showcase/vending-machine +++ b/showcase/vending-machine @@ -1 +1 @@ -Subproject commit fb58bec04872d3b9a7ef67191a77842db42ba849 +Subproject commit 3584d8b038897ebf5c7fecc68acdd131b7b425ea From d534a91a65db29634392b01ab803d43e03dab050 Mon Sep 17 00:00:00 2001 From: psymed Date: Thu, 20 Feb 2025 19:31:35 +0200 Subject: [PATCH 26/34] feat(showcase): Add comprehensive web automation testing demo by ShAI Bernard Lelchuk --- .gitmodules | 3 +++ showcase/tdd-web-automation | 1 + 2 files changed, 4 insertions(+) create mode 160000 showcase/tdd-web-automation diff --git a/.gitmodules b/.gitmodules index b05c2e0..c656af7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "showcase/vending-machine"] path = showcase/vending-machine url = https://github.com/ShAIWhisperer/vending-machine.git +[submodule "showcase/tdd-web-automation"] + path = showcase/tdd-web-automation + url = https://github.com/ShAIWhisperer/tdd-web-automation.git diff --git a/showcase/tdd-web-automation b/showcase/tdd-web-automation new file mode 160000 index 0000000..19fe18f --- /dev/null +++ b/showcase/tdd-web-automation @@ -0,0 +1 @@ +Subproject commit 19fe18f03952c0595cd2fbb9a5d5359f4a36fe6f From 6255d85fd8faed172997e7d3b98cd71acecadfb4 Mon Sep 17 00:00:00 2001 From: brandonkachen Date: Thu, 20 Feb 2025 15:31:36 -0800 Subject: [PATCH 27/34] chore: update showcase README --- showcase/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/showcase/README.md b/showcase/README.md index fdb5c56..4a161a8 100644 --- a/showcase/README.md +++ b/showcase/README.md @@ -10,8 +10,12 @@ Community showcase of projects built by Codebuff - [Maze Generator](https://github.com/narthur/maze-gen) - A maze generation visualization built with TypeScript - [Codebuff Tricks](https://github.com/narthur/codebuff-tricks) - A community-built wizard to help you set up new projects with Codebuff - Minecraft simple - A basic version of Minecraft running in the browser! +- Minecraft complex - A more complex version of Minecraft running in the browser! - Fishies - An aquarium with various fishies - Code Analysis - A project by [Lachlan Gray](https://github.com/LachlanGray) to show interesting stats on any Github repo +- [Calendar On Air](https://gist.github.com/dhunten/7f88654f3972bfe0fc6d70a1b5fa024a/b2e2b25e788ca7a50c42f3a5a991f4b860e37306) - An app built with CircuitPython that pulls time and weather data + a user's calendar events from the internet and displays it on an LCD screen +- [TDD Web Automation](https://github.com/ShAIWhisperer/tdd-web-automation) - A React-based web application demonstrating form automation testing using Playwright, uisng Test Driven Development (TDD) +- [Vending Machine](https://github.com/ShAIWhisperer/vending-machine) - A fun little vending machine web and cli ## Vending Machine A showcase project demonstrating a modern vending machine interface with: From 34b94af2dfef30d84d8b863e1a492335c65e080d Mon Sep 17 00:00:00 2001 From: brandon chen <9735006+brandonkachen@users.noreply.github.com> Date: Mon, 24 Feb 2025 12:13:06 -0800 Subject: [PATCH 28/34] Update README.md --- showcase/README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/showcase/README.md b/showcase/README.md index 4a161a8..34d13ba 100644 --- a/showcase/README.md +++ b/showcase/README.md @@ -17,13 +17,6 @@ Community showcase of projects built by Codebuff - [TDD Web Automation](https://github.com/ShAIWhisperer/tdd-web-automation) - A React-based web application demonstrating form automation testing using Playwright, uisng Test Driven Development (TDD) - [Vending Machine](https://github.com/ShAIWhisperer/vending-machine) - A fun little vending machine web and cli -## Vending Machine -A showcase project demonstrating a modern vending machine interface with: -- Interactive UI with animations -- Product selection and purchase flow -- Testing implementation -- [Link to repository](https://github.com/ShAIWhisperer/vending-machine) - ## Cloning This repository contains submodules. To clone including all showcase projects, use: From a527be9da83878970887b11c06915f3c110c799f Mon Sep 17 00:00:00 2001 From: brandon chen <9735006+brandonkachen@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:13:34 -0800 Subject: [PATCH 29/34] Update .gitmodules --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index c656af7..3e1c151 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "showcase/tdd-web-automation"] path = showcase/tdd-web-automation url = https://github.com/ShAIWhisperer/tdd-web-automation.git +[submodule "showcase/timer"] + path = showcase/timer + url = https://github.com/charleslien/timer.git From 8909110af62f1cbb5b59d9cd1fd70c559c1e80c7 Mon Sep 17 00:00:00 2001 From: brandonkachen Date: Mon, 24 Feb 2025 16:19:51 -0800 Subject: [PATCH 30/34] feat: added Charles Lien's Timer project! --- showcase/README.md | 1 + showcase/timer | 1 + 2 files changed, 2 insertions(+) create mode 160000 showcase/timer diff --git a/showcase/README.md b/showcase/README.md index 34d13ba..f622dfb 100644 --- a/showcase/README.md +++ b/showcase/README.md @@ -16,6 +16,7 @@ Community showcase of projects built by Codebuff - [Calendar On Air](https://gist.github.com/dhunten/7f88654f3972bfe0fc6d70a1b5fa024a/b2e2b25e788ca7a50c42f3a5a991f4b860e37306) - An app built with CircuitPython that pulls time and weather data + a user's calendar events from the internet and displays it on an LCD screen - [TDD Web Automation](https://github.com/ShAIWhisperer/tdd-web-automation) - A React-based web application demonstrating form automation testing using Playwright, uisng Test Driven Development (TDD) - [Vending Machine](https://github.com/ShAIWhisperer/vending-machine) - A fun little vending machine web and cli +- [Timer App](https://github.com/charleslien/timer.git) - A timer app by [Charles Lien](https://github.com/charleslien) to track various tasks over the years. ## Cloning diff --git a/showcase/timer b/showcase/timer new file mode 160000 index 0000000..46c18bc --- /dev/null +++ b/showcase/timer @@ -0,0 +1 @@ +Subproject commit 46c18bc12ceb4bbd160bd46cad5033d9cb897894 From 9b96f8db1570d675d9c9ff420472d50ee0769e6a Mon Sep 17 00:00:00 2001 From: Charles Lien Date: Wed, 23 Apr 2025 17:50:35 -0700 Subject: [PATCH 31/34] Init all starter-templates --- starter-templates/chrome-extension/.gitignore | 2 +- .../chrome-extension/codebuff.json | 19 +++++++++++++++++++ starter-templates/convex/.gitignore | 3 +++ starter-templates/convex/codebuff.json | 19 +++++++++++++++++++ starter-templates/nextjs/.gitignore | 3 +++ starter-templates/nextjs/codebuff.json | 19 +++++++++++++++++++ starter-templates/node-cli/.gitignore | 2 +- starter-templates/node-cli/codebuff.json | 19 +++++++++++++++++++ starter-templates/python-cli/.gitignore | 2 +- starter-templates/python-cli/codebuff.json | 4 ++++ starter-templates/remix/.gitignore | 1 + starter-templates/remix/codebuff.json | 19 +++++++++++++++++++ starter-templates/vite/.gitignore | 2 +- starter-templates/vite/codebuff.json | 19 +++++++++++++++++++ 14 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 starter-templates/chrome-extension/codebuff.json create mode 100644 starter-templates/convex/codebuff.json create mode 100644 starter-templates/nextjs/codebuff.json create mode 100644 starter-templates/node-cli/codebuff.json create mode 100644 starter-templates/python-cli/codebuff.json create mode 100644 starter-templates/remix/codebuff.json create mode 100644 starter-templates/vite/codebuff.json diff --git a/starter-templates/chrome-extension/.gitignore b/starter-templates/chrome-extension/.gitignore index 9451024..860f969 100644 --- a/starter-templates/chrome-extension/.gitignore +++ b/starter-templates/chrome-extension/.gitignore @@ -1,4 +1,4 @@ node_modules/ dist/ .DS_Store -*.log +**.log diff --git a/starter-templates/chrome-extension/codebuff.json b/starter-templates/chrome-extension/codebuff.json new file mode 100644 index 0000000..7b1e09b --- /dev/null +++ b/starter-templates/chrome-extension/codebuff.json @@ -0,0 +1,19 @@ +{ + "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", + "startupProcesses": [ + { + "name": "dev", + "command": "npm run dev", + "enabled": true, + "stdoutFile": "logs/dev.log", + "stderrFile": "logs/dev.log" + }, + { + "name": "typecheck", + "command": "npm run typecheck -- --watch", + "enabled": true, + "stdoutFile": "logs/typecheck.log", + "stderrFile": "logs/typecheck.log" + } + ] +} \ No newline at end of file diff --git a/starter-templates/convex/.gitignore b/starter-templates/convex/.gitignore index 8777267..3889b14 100644 --- a/starter-templates/convex/.gitignore +++ b/starter-templates/convex/.gitignore @@ -38,3 +38,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# log files +**.log diff --git a/starter-templates/convex/codebuff.json b/starter-templates/convex/codebuff.json new file mode 100644 index 0000000..074459e --- /dev/null +++ b/starter-templates/convex/codebuff.json @@ -0,0 +1,19 @@ +{ + "description": "Real-time chat application with Convex backend and Next.js frontend", + "startupProcesses": [ + { + "name": "dev", + "command": "npm run dev", + "enabled": true, + "stdoutFile": "logs/dev.log", + "stderrFile": "logs/dev.log" + }, + { + "name": "typecheck", + "command": "npm run typecheck -- --watch", + "enabled": true, + "stdoutFile": "logs/typecheck.log", + "stderrFile": "logs/typecheck.log" + } + ] +} \ No newline at end of file diff --git a/starter-templates/nextjs/.gitignore b/starter-templates/nextjs/.gitignore index 5ef6a52..89ce329 100644 --- a/starter-templates/nextjs/.gitignore +++ b/starter-templates/nextjs/.gitignore @@ -39,3 +39,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# log files +**.log diff --git a/starter-templates/nextjs/codebuff.json b/starter-templates/nextjs/codebuff.json new file mode 100644 index 0000000..7b1e09b --- /dev/null +++ b/starter-templates/nextjs/codebuff.json @@ -0,0 +1,19 @@ +{ + "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", + "startupProcesses": [ + { + "name": "dev", + "command": "npm run dev", + "enabled": true, + "stdoutFile": "logs/dev.log", + "stderrFile": "logs/dev.log" + }, + { + "name": "typecheck", + "command": "npm run typecheck -- --watch", + "enabled": true, + "stdoutFile": "logs/typecheck.log", + "stderrFile": "logs/typecheck.log" + } + ] +} \ No newline at end of file diff --git a/starter-templates/node-cli/.gitignore b/starter-templates/node-cli/.gitignore index 9451024..860f969 100644 --- a/starter-templates/node-cli/.gitignore +++ b/starter-templates/node-cli/.gitignore @@ -1,4 +1,4 @@ node_modules/ dist/ .DS_Store -*.log +**.log diff --git a/starter-templates/node-cli/codebuff.json b/starter-templates/node-cli/codebuff.json new file mode 100644 index 0000000..7b1e09b --- /dev/null +++ b/starter-templates/node-cli/codebuff.json @@ -0,0 +1,19 @@ +{ + "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", + "startupProcesses": [ + { + "name": "dev", + "command": "npm run dev", + "enabled": true, + "stdoutFile": "logs/dev.log", + "stderrFile": "logs/dev.log" + }, + { + "name": "typecheck", + "command": "npm run typecheck -- --watch", + "enabled": true, + "stdoutFile": "logs/typecheck.log", + "stderrFile": "logs/typecheck.log" + } + ] +} \ No newline at end of file diff --git a/starter-templates/python-cli/.gitignore b/starter-templates/python-cli/.gitignore index 53aa933..dfc60df 100644 --- a/starter-templates/python-cli/.gitignore +++ b/starter-templates/python-cli/.gitignore @@ -5,7 +5,7 @@ __pycache__/ .venv/ venv/ .DS_Store -*.log +**.log dist/ build/ *.egg-info/ diff --git a/starter-templates/python-cli/codebuff.json b/starter-templates/python-cli/codebuff.json new file mode 100644 index 0000000..5e6e020 --- /dev/null +++ b/starter-templates/python-cli/codebuff.json @@ -0,0 +1,4 @@ +{ + "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", + "startupProcesses": [] +} \ No newline at end of file diff --git a/starter-templates/remix/.gitignore b/starter-templates/remix/.gitignore index 80ec311..b43fc49 100644 --- a/starter-templates/remix/.gitignore +++ b/starter-templates/remix/.gitignore @@ -3,3 +3,4 @@ node_modules /.cache /build .env +**.log diff --git a/starter-templates/remix/codebuff.json b/starter-templates/remix/codebuff.json new file mode 100644 index 0000000..7b1e09b --- /dev/null +++ b/starter-templates/remix/codebuff.json @@ -0,0 +1,19 @@ +{ + "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", + "startupProcesses": [ + { + "name": "dev", + "command": "npm run dev", + "enabled": true, + "stdoutFile": "logs/dev.log", + "stderrFile": "logs/dev.log" + }, + { + "name": "typecheck", + "command": "npm run typecheck -- --watch", + "enabled": true, + "stdoutFile": "logs/typecheck.log", + "stderrFile": "logs/typecheck.log" + } + ] +} \ No newline at end of file diff --git a/starter-templates/vite/.gitignore b/starter-templates/vite/.gitignore index a547bf3..bef1132 100644 --- a/starter-templates/vite/.gitignore +++ b/starter-templates/vite/.gitignore @@ -1,6 +1,6 @@ # Logs logs -*.log +**.log npm-debug.log* yarn-debug.log* yarn-error.log* diff --git a/starter-templates/vite/codebuff.json b/starter-templates/vite/codebuff.json new file mode 100644 index 0000000..7b1e09b --- /dev/null +++ b/starter-templates/vite/codebuff.json @@ -0,0 +1,19 @@ +{ + "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", + "startupProcesses": [ + { + "name": "dev", + "command": "npm run dev", + "enabled": true, + "stdoutFile": "logs/dev.log", + "stderrFile": "logs/dev.log" + }, + { + "name": "typecheck", + "command": "npm run typecheck -- --watch", + "enabled": true, + "stdoutFile": "logs/typecheck.log", + "stderrFile": "logs/typecheck.log" + } + ] +} \ No newline at end of file From 22b14d2ca3eb950ea0f7550890712af2226da255 Mon Sep 17 00:00:00 2001 From: Charles Lien Date: Tue, 3 Jun 2025 16:03:10 -0700 Subject: [PATCH 32/34] add fileChangeHooks --- .../chrome-extension/codebuff.json | 18 +++++++++++------- starter-templates/convex/codebuff.json | 17 ++++++++--------- starter-templates/nextjs/codebuff.json | 18 +++++++++++------- starter-templates/node-cli/codebuff.json | 15 +++++++-------- starter-templates/python-cli/codebuff.json | 16 ++++++++++++++-- starter-templates/remix/codebuff.json | 18 +++++++++++------- starter-templates/vite/codebuff.json | 18 +++++++++++------- 7 files changed, 73 insertions(+), 47 deletions(-) diff --git a/starter-templates/chrome-extension/codebuff.json b/starter-templates/chrome-extension/codebuff.json index 7b1e09b..d225ced 100644 --- a/starter-templates/chrome-extension/codebuff.json +++ b/starter-templates/chrome-extension/codebuff.json @@ -5,15 +5,19 @@ "name": "dev", "command": "npm run dev", "enabled": true, - "stdoutFile": "logs/dev.log", - "stderrFile": "logs/dev.log" + "stdoutFile": "logs/dev.log" + } + ], + "fileChangeHooks": [ + { + "name": "lint", + "command": "npm run lint -- --fix", + "enabled": true }, { "name": "typecheck", - "command": "npm run typecheck -- --watch", - "enabled": true, - "stdoutFile": "logs/typecheck.log", - "stderrFile": "logs/typecheck.log" + "command": "npm run typecheck", + "enabled": true } ] -} \ No newline at end of file +} diff --git a/starter-templates/convex/codebuff.json b/starter-templates/convex/codebuff.json index 074459e..ca94de1 100644 --- a/starter-templates/convex/codebuff.json +++ b/starter-templates/convex/codebuff.json @@ -1,19 +1,18 @@ { - "description": "Real-time chat application with Convex backend and Next.js frontend", + "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", "startupProcesses": [ { "name": "dev", "command": "npm run dev", "enabled": true, - "stdoutFile": "logs/dev.log", - "stderrFile": "logs/dev.log" - }, + "stdoutFile": "logs/dev.log" + } + ], + "fileChangeHooks": [ { "name": "typecheck", - "command": "npm run typecheck -- --watch", - "enabled": true, - "stdoutFile": "logs/typecheck.log", - "stderrFile": "logs/typecheck.log" + "command": "npm run typecheck", + "enabled": true } ] -} \ No newline at end of file +} diff --git a/starter-templates/nextjs/codebuff.json b/starter-templates/nextjs/codebuff.json index 7b1e09b..d225ced 100644 --- a/starter-templates/nextjs/codebuff.json +++ b/starter-templates/nextjs/codebuff.json @@ -5,15 +5,19 @@ "name": "dev", "command": "npm run dev", "enabled": true, - "stdoutFile": "logs/dev.log", - "stderrFile": "logs/dev.log" + "stdoutFile": "logs/dev.log" + } + ], + "fileChangeHooks": [ + { + "name": "lint", + "command": "npm run lint -- --fix", + "enabled": true }, { "name": "typecheck", - "command": "npm run typecheck -- --watch", - "enabled": true, - "stdoutFile": "logs/typecheck.log", - "stderrFile": "logs/typecheck.log" + "command": "npm run typecheck", + "enabled": true } ] -} \ No newline at end of file +} diff --git a/starter-templates/node-cli/codebuff.json b/starter-templates/node-cli/codebuff.json index 7b1e09b..ca94de1 100644 --- a/starter-templates/node-cli/codebuff.json +++ b/starter-templates/node-cli/codebuff.json @@ -5,15 +5,14 @@ "name": "dev", "command": "npm run dev", "enabled": true, - "stdoutFile": "logs/dev.log", - "stderrFile": "logs/dev.log" - }, + "stdoutFile": "logs/dev.log" + } + ], + "fileChangeHooks": [ { "name": "typecheck", - "command": "npm run typecheck -- --watch", - "enabled": true, - "stdoutFile": "logs/typecheck.log", - "stderrFile": "logs/typecheck.log" + "command": "npm run typecheck", + "enabled": true } ] -} \ No newline at end of file +} diff --git a/starter-templates/python-cli/codebuff.json b/starter-templates/python-cli/codebuff.json index 5e6e020..aee9189 100644 --- a/starter-templates/python-cli/codebuff.json +++ b/starter-templates/python-cli/codebuff.json @@ -1,4 +1,16 @@ { "description": "Template configuration for this project. See https://www.codebuff.com/config for all options.", - "startupProcesses": [] -} \ No newline at end of file + "startupProcesses": [], + "fileChangeHooks": [ + { + "name": "lint", + "command": "python3 -m flake8 .", + "enabled": true + }, + { + "name": "test", + "command": "python3 -m unittest discover -s tests", + "enabled": true + } + ] +} diff --git a/starter-templates/remix/codebuff.json b/starter-templates/remix/codebuff.json index 7b1e09b..d225ced 100644 --- a/starter-templates/remix/codebuff.json +++ b/starter-templates/remix/codebuff.json @@ -5,15 +5,19 @@ "name": "dev", "command": "npm run dev", "enabled": true, - "stdoutFile": "logs/dev.log", - "stderrFile": "logs/dev.log" + "stdoutFile": "logs/dev.log" + } + ], + "fileChangeHooks": [ + { + "name": "lint", + "command": "npm run lint -- --fix", + "enabled": true }, { "name": "typecheck", - "command": "npm run typecheck -- --watch", - "enabled": true, - "stdoutFile": "logs/typecheck.log", - "stderrFile": "logs/typecheck.log" + "command": "npm run typecheck", + "enabled": true } ] -} \ No newline at end of file +} diff --git a/starter-templates/vite/codebuff.json b/starter-templates/vite/codebuff.json index 7b1e09b..d225ced 100644 --- a/starter-templates/vite/codebuff.json +++ b/starter-templates/vite/codebuff.json @@ -5,15 +5,19 @@ "name": "dev", "command": "npm run dev", "enabled": true, - "stdoutFile": "logs/dev.log", - "stderrFile": "logs/dev.log" + "stdoutFile": "logs/dev.log" + } + ], + "fileChangeHooks": [ + { + "name": "lint", + "command": "npm run lint -- --fix", + "enabled": true }, { "name": "typecheck", - "command": "npm run typecheck -- --watch", - "enabled": true, - "stdoutFile": "logs/typecheck.log", - "stderrFile": "logs/typecheck.log" + "command": "npm run typecheck", + "enabled": true } ] -} \ No newline at end of file +} From 30e5b1eae8390ab356ea9bc834ac8d07e2362a4e Mon Sep 17 00:00:00 2001 From: Stephen Gibson Date: Tue, 22 Jul 2025 21:11:36 -0700 Subject: [PATCH 33/34] Fix: make stat cross-platform compatible (macOS/Linux) --- utils/docker/start-codebuff.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/utils/docker/start-codebuff.sh b/utils/docker/start-codebuff.sh index 3f2c006..bea85d3 100755 --- a/utils/docker/start-codebuff.sh +++ b/utils/docker/start-codebuff.sh @@ -35,6 +35,15 @@ cleanup() { } trap cleanup SIGINT SIGTERM EXIT +# Determine correct 'stat' syntax based on platform (BSD/macOS vs GNU/Linux) +if stat -c %Y / >/dev/null 2>&1; then + # GNU stat (Linux) + STAT_CMD="stat -c" +else + # BSD stat (macOS, FreeBSD, etc.) + STAT_CMD="stat -f" +fi + # Get the directory where this script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -51,10 +60,10 @@ if ! docker images codebuff --format "{{.ID}}" | grep -q .; then docker build -t codebuff "$SCRIPT_DIR" || { error "Failed to build Docker image"; exit 1; } else # Always rebuild if any of the scripts have been modified - DOCKERFILE_MTIME=$(stat -f %m "$SCRIPT_DIR/Dockerfile") - WRAPPER_MTIME=$(stat -f %m "$SCRIPT_DIR/codebuff-wrapper.sh") - ENTRYPOINT_MTIME=$(stat -f %m "$SCRIPT_DIR/entrypoint.sh") - BRIDGE_MTIME=$(stat -f %m "$SCRIPT_DIR/message-bridge.sh") + DOCKERFILE_MTIME=$($STAT_CMD %m "$SCRIPT_DIR/Dockerfile") + WRAPPER_MTIME=$($STAT_CMD %m "$SCRIPT_DIR/codebuff-wrapper.sh") + ENTRYPOINT_MTIME=$($STAT_CMD %m "$SCRIPT_DIR/entrypoint.sh") + BRIDGE_MTIME=$($STAT_CMD %m "$SCRIPT_DIR/message-bridge.sh") # Get the most recent modification time LATEST_MTIME=$DOCKERFILE_MTIME @@ -65,7 +74,7 @@ else done debug "Latest modification time: $LATEST_MTIME" - debug "Raw modification time: $(stat -f %Sm "$SCRIPT_DIR/Dockerfile")" + debug "Raw modification time: $($STAT_CMD %Sm "$SCRIPT_DIR/Dockerfile")" # Always rebuild for now - safer while we're actively developing log "Scripts may have been modified. Rebuilding image..." From 10ae02e0e9436bea031b9d950d19310238c7c191 Mon Sep 17 00:00:00 2001 From: Brent Wilkins Date: Thu, 4 Sep 2025 11:35:08 -0600 Subject: [PATCH 34/34] chore (python-cli): Version bump with related improvements (October version) * Bumped Python version to the oldest currently supported version (3.10) * Made the `cli` package get its version via the installed package or ultimately from `pyproject.toml` for a single source of truth on that * Added testing for new single source of truth version code to a CI workflow * A few [CommonMark](https://commonmark.org/) compliancy tweaks in the markdown files * I had to use `.python-version` to get such an old version running for testing, so I sorted and added that to `.gitignore` --- .../.github/workflows/test-version.yml | 82 +++++++++++++++++++ starter-templates/python-cli/.gitignore | 15 ++-- starter-templates/python-cli/README.md | 1 + starter-templates/python-cli/cli/__init__.py | 13 ++- starter-templates/python-cli/knowledge.md | 5 ++ starter-templates/python-cli/pyproject.toml | 19 +++-- 6 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 starter-templates/python-cli/.github/workflows/test-version.yml diff --git a/starter-templates/python-cli/.github/workflows/test-version.yml b/starter-templates/python-cli/.github/workflows/test-version.yml new file mode 100644 index 0000000..453c080 --- /dev/null +++ b/starter-templates/python-cli/.github/workflows/test-version.yml @@ -0,0 +1,82 @@ +name: Test Version Management + +on: + push: + branches: [ main, develop ] + tags: + - 'v*' + pull_request: + branches: [ main ] + +jobs: + test-version: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for version tools that use git + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install package and dev dependencies + run: | + python -m pip install --upgrade pip + pip install -e .[dev] + + - name: Test version can be imported + run: | + python -c "import cli; print(f'Package version: {cli.__version__}')" + + - name: Test importlib.metadata version access + run: | + python -c "import importlib.metadata; version = importlib.metadata.version('cli'); print(f'Metadata version: {version}')" + + - name: Verify version consistency + run: | + # Get version from package import + IMPORT_VERSION=$(python -c "import cli; print(cli.__version__)") + # Get version from metadata + METADATA_VERSION=$(python -c "import importlib.metadata; print(importlib.metadata.version('cli'))") + + echo "Import version: $IMPORT_VERSION" + echo "Metadata version: $METADATA_VERSION" + + if [ "$IMPORT_VERSION" != "$METADATA_VERSION" ]; then + echo "ERROR: Version mismatch between import and metadata!" + exit 1 + fi + + echo "SUCCESS: Version consistency verified" + + + - name: Run type checking and formatting + run: | + mypy cli + black --check cli + + # Only run on tag pushes to verify git tag matches version + - name: Verify version matches git tag + if: startsWith(github.ref, 'refs/tags/v') + run: | + # Extract version from git tag (e.g., 'v1.2.3' -> '1.2.3') + TAG_VERSION=${GITHUB_REF#refs/tags/v} + # Get version from installed package + INSTALLED_VERSION=$(python -c "import importlib.metadata; print(importlib.metadata.version('cli'))") + + echo "Git tag version: $TAG_VERSION" + echo "Installed version: $INSTALLED_VERSION" + + if [ "$TAG_VERSION" != "$INSTALLED_VERSION" ]; then + echo "ERROR: Git tag version doesn't match installed version!" + exit 1 + fi + + echo "SUCCESS: Git tag and installed versions match" diff --git a/starter-templates/python-cli/.gitignore b/starter-templates/python-cli/.gitignore index dfc60df..d7dd712 100644 --- a/starter-templates/python-cli/.gitignore +++ b/starter-templates/python-cli/.gitignore @@ -1,11 +1,12 @@ -__pycache__/ -*.py[cod] *$py.class +**.log +*.egg-info/ +*.py[cod] +.DS_Store .env +.python-version .venv/ -venv/ -.DS_Store -**.log -dist/ +__pycache__/ build/ -*.egg-info/ +dist/ +venv/ diff --git a/starter-templates/python-cli/README.md b/starter-templates/python-cli/README.md index 8632681..7b2f470 100644 --- a/starter-templates/python-cli/README.md +++ b/starter-templates/python-cli/README.md @@ -32,6 +32,7 @@ pip install dist/*.whl ``` ## Project Structure + - `cli/` - Source files - `tests/` - Test files - `pyproject.toml` - Project configuration diff --git a/starter-templates/python-cli/cli/__init__.py b/starter-templates/python-cli/cli/__init__.py index ebf5982..31ac525 100644 --- a/starter-templates/python-cli/cli/__init__.py +++ b/starter-templates/python-cli/cli/__init__.py @@ -1,3 +1,14 @@ """A Python CLI application.""" -__version__ = "0.1.0" +from importlib.metadata import PackageNotFoundError, version + +try: + __version__ = version("cli") +except PackageNotFoundError: + # Package not installed, fallback for development + try: + import toml # type: ignore[import-untyped] + + __version__ = toml.load("pyproject.toml")["project"]["version"] + except Exception: + __version__ = "unknown" diff --git a/starter-templates/python-cli/knowledge.md b/starter-templates/python-cli/knowledge.md index be474f6..e3124da 100644 --- a/starter-templates/python-cli/knowledge.md +++ b/starter-templates/python-cli/knowledge.md @@ -1,17 +1,22 @@ # Python CLI Template Knowledge ## Project Overview + A minimal Python CLI application template with modern Python features and type hints. ## Key Features + - Uses virtual environments for isolation - Type hints and mypy for static type checking - Modern Python packaging with pyproject.toml - Black for code formatting ## Verifying changes + After every change, run: + ```bash mypy cli && black --check cli ``` + This will check for type errors and formatting issues. diff --git a/starter-templates/python-cli/pyproject.toml b/starter-templates/python-cli/pyproject.toml index 3eea2b6..ebb276c 100644 --- a/starter-templates/python-cli/pyproject.toml +++ b/starter-templates/python-cli/pyproject.toml @@ -2,27 +2,28 @@ name = "cli" version = "0.1.0" description = "A Python CLI application" -requires-python = ">=3.8" +requires-python = ">=3.10" dependencies = [] [project.optional-dependencies] dev = [ - "mypy>=1.8.0", - "black>=24.1.1", - "pytest>=8.0.0", + "black>=25.1.0", + "mypy>=1.17.1", + "pytest>=8.4.2", + "toml>=0.10.2", # In case someone forgets to run `pip install -e ".[dev]"` ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" +[tool.black] +line-length = 88 +target-version = ['py310'] + [tool.mypy] -python_version = "3.8" +python_version = "3.10" strict = true warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true - -[tool.black] -line-length = 88 -target-version = ['py38']