diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d25f099 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,106 @@ +# Docker ignore file for LLM Orchestration Service +# Exclude unnecessary files from Docker build context + +# Git +.git +.gitignore + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Virtual environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Logs +*.log +logs/ +*.log.* + +# Testing +.pytest_cache/ +.coverage +htmlcov/ +.tox/ +coverage.xml + +# Documentation +docs/ +*.md +!README.md + +# Config files (will be mounted) +.env.local +.env.development +.env.test + +# Cache directories +.ruff_cache/ +.mypy_cache/ +.pyright_cache/ + +# Test files +test_*.py +*_test.py +tests/ + +# Development scripts +run_*.py +test_*.py + +# Temporary files +*.tmp +*.temp +.temporary + +# Node modules (if any) +node_modules/ + +# Docker files (except the specific one being built) +Dockerfile* +!Dockerfile.llm_orchestration_service +docker-compose*.yml + +# Grafana configs (not needed for this service) +grafana-configs/ diff --git a/.env.example b/.env.example deleted file mode 100644 index fd40910..0000000 --- a/.env.example +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/.github/workflows/deepeval-tests.yml b/.github/workflows/deepeval-tests.yml new file mode 100644 index 0000000..5da84df --- /dev/null +++ b/.github/workflows/deepeval-tests.yml @@ -0,0 +1,123 @@ +name: DeepEval RAG System Tests + +on: + pull_request: + types: [opened, synchronize, reopened] + paths: + - 'src/**' + - 'tests/**' + - '.github/workflows/deepeval-tests.yml' + +jobs: + deepeval-tests: + runs-on: ubuntu-latest + timeout-minutes: 40 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: '.python-version' + + - name: Set up uv + uses: astral-sh/setup-uv@v6 + + - name: Install dependencies (locked) + run: uv sync --frozen + + - name: Run DeepEval tests + id: run_tests + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + run: uv run python -m pytest tests/deepeval_tests/standard_tests.py -v --tb=short + + - name: Generate evaluation report + if: always() + run: python tests/deepeval_tests/report_generator.py + + - name: Comment PR with test results + if: always() && github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + try { + const reportContent = fs.readFileSync('test_report.md', 'utf8'); + + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number + }); + + const existingComment = comments.data.find( + comment => comment.user.login === 'github-actions[bot]' && + comment.body.includes('RAG System Evaluation Report') + ); + + if (existingComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingComment.id, + body: reportContent + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: reportContent + }); + } + + } catch (error) { + console.error('Failed to post test results:', error); + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `## RAG System Evaluation Report\n\n**Error generating test report**\n\nFailed to read or post test results. Check workflow logs for details.\n\nError: ${error.message}` + }); + } + + - name: Check test results and fail if needed + if: always() + run: | + # Check if pytest ran (look at step output) + if [ "${{ steps.run_tests.outcome }}" == "failure" ]; then + echo "Tests ran but failed - this is expected if RAG performance is below threshold" + fi + if [ -f "pytest_captured_results.json" ]; then + total_tests=$(jq '.total_tests // 0' pytest_captured_results.json) + passed_tests=$(jq '.passed_tests // 0' pytest_captured_results.json) + + if [ "$total_tests" -eq 0 ]; then + echo "ERROR: No tests were executed" + exit 1 + fi + + pass_rate=$(awk "BEGIN {print ($passed_tests / $total_tests) * 100}") + + echo "DeepEval Test Results:" + echo "Total Tests: $total_tests" + echo "Passed Tests: $passed_tests" + echo "Pass Rate: $pass_rate%" + + if (( $(echo "$pass_rate < 70" | bc -l) )); then + echo "TEST FAILURE: Pass rate $pass_rate% is below threshold 70%" + echo "RAG system performance is below acceptable standards." + exit 1 + else + echo "TEST SUCCESS: Pass rate $pass_rate% meets threshold 70%" + fi + else + echo "ERROR: No test results file found" + exit 1 + fi \ No newline at end of file diff --git a/.github/workflows/deepteam-red-team-tests.yml b/.github/workflows/deepteam-red-team-tests.yml new file mode 100644 index 0000000..ba0861b --- /dev/null +++ b/.github/workflows/deepteam-red-team-tests.yml @@ -0,0 +1,167 @@ +name: DeepTeam Red Team Security Tests + +on: + pull_request: + types: [opened, synchronize, reopened] + paths: + - 'src/**' + - 'tests/**' + - 'mocks/**' + - 'data/**' + - '.github/workflows/deepeval-red-team-tests.yml' + workflow_dispatch: + inputs: + attack_intensity: + description: 'Attack intensity level' + required: false + default: 'standard' + type: choice + options: + - light + - standard + - intensive + +jobs: + security-assessment: + runs-on: ubuntu-latest + timeout-minutes: 60 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: '.python-version' + + - name: Set up uv + uses: astral-sh/setup-uv@v6 + + - name: Install dependencies (locked) + run: uv sync --frozen + + - name: Run Complete Security Assessment + id: run_tests + continue-on-error: true + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + run: | + # Run all security tests in one comprehensive session + uv run python -m pytest tests/deepeval_tests/red_team_tests.py::TestRAGSystemRedTeaming -v --tb=short + + - name: Generate Security Report + if: always() + run: | + if [ -f tests/deepeval_tests/red_team_report_generator.py ]; then + uv run python tests/deepeval_tests/red_team_report_generator.py || true + fi + + - name: Comment PR with Security Results + if: always() && github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + try { + let reportContent = ''; + if (fs.existsSync('security_report.md')) { + reportContent = fs.readFileSync('security_report.md', 'utf8'); + } else { + // Fallback: create basic report from JSON + let results = {}; + if (fs.existsSync('pytest_captured_results.json')) { + const resultsData = fs.readFileSync('pytest_captured_results.json', 'utf8'); + results = JSON.parse(resultsData); + } + + const totalTests = results.total_tests || 0; + const passedTests = results.passed_tests || 0; + const failedTests = results.failed_tests || 0; + const passRate = totalTests > 0 ? (passedTests / totalTests * 100) : 0; + const status = passRate >= 70 ? 'SECURE' : 'VULNERABLE'; + + reportContent = `# RAG System Security Assessment Report\n\n` + + `**Status**: ${status}\n` + + `**Pass Rate**: ${passRate.toFixed(1)}% (${passedTests}/${totalTests} tests)\n` + + `**Failed Tests**: ${failedTests}\n\n`; + + if (passRate < 70) { + reportContent += `**Security vulnerabilities detected!** This PR introduces or fails to address security issues.\n\n`; + } else { + reportContent += `All security tests passed.\n\n`; + } + } + + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number + }); + + const existingComment = comments.data.find( + comment => comment.user.login === 'github-actions[bot]' && + comment.body.includes('RAG System Security Assessment Report') + ); + + if (existingComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingComment.id, + body: reportContent + }); + console.log('Updated existing security comment'); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: reportContent + }); + console.log('Created new security comment'); + } + + } catch (error) { + console.error('Failed to post security results:', error); + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `# Security Test Results\n\n**Error generating security report**\n\nFailed to read or post security results. Check workflow logs for details.\n\nError: ${error.message}` + }); + } + + - name: Check test results and fail if needed + if: always() + run: | + if [ -f "pytest_captured_results.json" ]; then + total_tests=$(jq '.total_tests // 0' pytest_captured_results.json) + passed_tests=$(jq '.passed_tests // 0' pytest_captured_results.json) + + if [ "$total_tests" -eq 0 ]; then + echo "ERROR: No tests were executed" + exit 1 + fi + + pass_rate=$(awk "BEGIN {print ($passed_tests / $total_tests) * 100}") + + echo "Complete Security Assessment Results:" + echo "Total Tests: $total_tests" + echo "Passed Tests: $passed_tests" + echo "Pass Rate: $pass_rate%" + + if (( $(echo "$pass_rate < 70" | bc -l) )); then + echo "TEST FAILURE: Pass rate $pass_rate% is below threshold 70%" + echo "Security vulnerabilities detected in RAG system." + exit 1 + else + echo "TEST SUCCESS: Pass rate $pass_rate% meets threshold 70%" + fi + else + echo "ERROR: No test results file found" + exit 1 + fi \ No newline at end of file diff --git a/.github/workflows/gui-eslint-check.yml b/.github/workflows/gui-eslint-check.yml new file mode 100644 index 0000000..df3b045 --- /dev/null +++ b/.github/workflows/gui-eslint-check.yml @@ -0,0 +1,32 @@ +name: RAG GUI eslint check + +on: + pull_request: + branches: ["*"] + push: + branches: ["*"] + +jobs: + lint: + name: Run ESLint + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'npm' + cache-dependency-path: 'GUI/package-lock.json' + + - name: Install dependencies + working-directory: ./GUI + run: npm install --legacy-peer-deps + + - name: Lint code + working-directory: ./GUI + run: npx eslint "src/**/*.{ts,tsx}" --quiet diff --git a/.github/workflows/pytest-integration-check.yml b/.github/workflows/pytest-integration-check.yml new file mode 100644 index 0000000..8b4b4cc --- /dev/null +++ b/.github/workflows/pytest-integration-check.yml @@ -0,0 +1,200 @@ +name: RAG Module Integration Tests + +on: + pull_request: + branches: [wip] + types: [opened, synchronize, reopened] + paths: + - 'src/**' + - 'tests/**' + - 'data/**' + - 'docker-compose-test.yml' + - 'Dockerfile.llm_orchestration_service' + - '.github/workflows/pytest-integration-check.yml' + +jobs: + pytest-integration-tests: + runs-on: ubuntu-latest + timeout-minutes: 80 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Validate required secrets + id: validate_secrets + run: | + echo "Validating required environment variables..." + MISSING_SECRETS=() + + # Check Azure OpenAI secrets + if [ -z "${{ secrets.AZURE_OPENAI_ENDPOINT }}" ]; then + MISSING_SECRETS+=("AZURE_OPENAI_ENDPOINT") + fi + + if [ -z "${{ secrets.AZURE_OPENAI_API_KEY }}" ]; then + MISSING_SECRETS+=("AZURE_OPENAI_API_KEY") + fi + + if [ -z "${{ secrets.AZURE_OPENAI_DEPLOYMENT_NAME }}" ]; then + MISSING_SECRETS+=("AZURE_OPENAI_DEPLOYMENT_NAME") + fi + + if [ -z "${{ secrets.AZURE_OPENAI_EMBEDDING_DEPLOYMENT }}" ]; then + MISSING_SECRETS+=("AZURE_OPENAI_EMBEDDING_DEPLOYMENT") + fi + + if [ -z "${{ secrets.AZURE_OPENAI_EMBEDDING_ENDPOINT }}" ]; then + MISSING_SECRETS+=("AZURE_OPENAI_EMBEDDING_ENDPOINT") + fi + + if [ -z "${{ secrets.SALT }}" ]; then + MISSING_SECRETS+=("SALT") + fi + + if [ -z "${{ secrets.ENCRYPTION_KEY }}" ]; then + MISSING_SECRETS+=("ENCRYPTION_KEY") + fi + + if [ -z "${{ secrets.NEXTAUTH_SECRET }}" ]; then + MISSING_SECRETS+=("NEXTAUTH_SECRET") + fi + + + # If any secrets are missing, fail + if [ ${#MISSING_SECRETS[@]} -gt 0 ]; then + echo "missing=true" >> $GITHUB_OUTPUT + echo "secrets_list=${MISSING_SECRETS[*]}" >> $GITHUB_OUTPUT + echo " Missing required secrets: ${MISSING_SECRETS[*]}" + exit 1 + else + echo "missing=false" >> $GITHUB_OUTPUT + echo " All required secrets are configured" + fi + + - name: Comment PR with missing secrets error + if: failure() && steps.validate_secrets.outputs.missing == 'true' + uses: actions/github-script@v7 + with: + script: | + const missingSecrets = '${{ steps.validate_secrets.outputs.secrets_list }}'.split(' '); + const secretsList = missingSecrets.map(s => `- \`${s}\``).join('\n'); + + const comment = `## RAG Module Integration Tests: Missing Required Secrets + + RAG Module Integration tests cannot run because the following GitHub secrets are not configured: + + ${secretsList} + + ### How to Fix + + 1. Go to **Settings** → **Secrets and variables** → **Actions** + 2. Add the missing secrets with the appropriate values: + + **Azure OpenAI Configuration:** + - \`AZURE_OPENAI_ENDPOINT\` - Your Azure OpenAI resource endpoint (e.g., \`https://your-resource.openai.azure.com/\`) + - \`AZURE_OPENAI_API_KEY\` - Your Azure OpenAI API key + - \`AZURE_OPENAI_DEPLOYMENT_NAME\` - Chat model deployment name (e.g., \`gpt-4o-mini\`) + - \`AZURE_OPENAI_EMBEDDING_DEPLOYMENT\` - Embedding model deployment name (e.g., \`text-embedding-3-large\`) + + + 3. Re-run the workflow after adding the secrets + + ### Note + Tests will not run until all required secrets are configured. + + --- + *Workflow: ${context.workflow} | Run: [#${context.runNumber}](${context.payload.repository.html_url}/actions/runs/${context.runId})*`; + + // Find existing comment + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number + }); + + const existingComment = comments.data.find( + comment => comment.user.login === 'github-actions[bot]' && + comment.body.includes('RAG Module Integration Tests: Missing Required Secrets') + ); + + if (existingComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingComment.id, + body: comment + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: comment + }); + } + + - name: Set up Python + if: success() + uses: actions/setup-python@v5 + with: + python-version-file: '.python-version' + + - name: Set up uv + if: success() + uses: astral-sh/setup-uv@v6 + + - name: Install dependencies (locked) + if: success() + run: uv sync --frozen + + - name: Create test directories with proper permissions + if: success() + run: | + mkdir -p test-vault/agents/llm + mkdir -p test-vault/agent-out + # Set ownership to current user and make writable + sudo chown -R $(id -u):$(id -g) test-vault + chmod -R 777 test-vault + # Ensure the agent-out directory is world-readable after writes + sudo chmod -R a+rwX test-vault/agent-out + + - name: Make Cron-Manager scripts executable + if: success() + run: | + chmod +x DSL/CronManager/script/*.sh + ls -la DSL/CronManager/script/ + + - name: Build Docker images + if: success() + run: docker compose -f docker-compose-test.yml build + + - name: Run Pytest Integration tests with testcontainers + if: success() + id: run_tests + env: + # Azure OpenAI - Chat Model + AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} + AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} + AZURE_OPENAI_DEPLOYMENT_NAME: ${{ secrets.AZURE_OPENAI_DEPLOYMENT_NAME }} + # Azure OpenAI - Embedding Model + AZURE_OPENAI_EMBEDDING_DEPLOYMENT: ${{ secrets.AZURE_OPENAI_EMBEDDING_DEPLOYMENT }} + AZURE_OPENAI_EMBEDDING_ENDPOINT: ${{ secrets.AZURE_OPENAI_EMBEDDING_ENDPOINT }} + SALT: ${{ secrets.SALT }} + ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }} + NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }} + run: | + # Run tests with testcontainers managing Docker Compose + uv run python -m pytest tests/integration_tests/ -v --tb=short --log-cli-level=INFO + + - name: Fix permissions on test artifacts + if: always() + run: | + sudo chown -R $(id -u):$(id -g) test-vault || true + sudo chmod -R a+rX test-vault || true + + - name: Cleanup Docker resources + if: always() + run: | + docker compose -f docker-compose-test.yml down -v --remove-orphans || true + docker system prune -f || true \ No newline at end of file diff --git a/.github/workflows/pytest-testcases-check.yml b/.github/workflows/pytest-testcases-check.yml deleted file mode 100644 index a147521..0000000 --- a/.github/workflows/pytest-testcases-check.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Pytest Testcases Check - -on: - pull_request: - branches: ["*"] # run on PRs to any branch - push: - branches: [main, dev, testing, wip] # optional; expand to ["*"] if you want all pushes - -jobs: - pytest-testcases: - name: Pytest Testcases Check - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version-file: '.python-version' - - - name: Set up uv - uses: astral-sh/setup-uv@v6 - - # Format check only — fails if files are not formatted - - name: Run test cases using Pytest - run: uv run pytest tests \ No newline at end of file diff --git a/.gitignore b/.gitignore index 434fde6..986ffff 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,15 @@ __pycache__/ *.py[cod] *$py.class .venv/ -.pytest_cache/ \ No newline at end of file +.pytest_cache/ +.env +tim-db +datasets +logs/ +data_sets +vault/agent-out + +# Snyk Security Extension - AI Rules (auto-generated) +.github/instructions/snyk_rules.instructions.md +# Dynamically created Ruuter health endpoint for tests +DSL/Ruuter.private/rag-search/GET/health.yml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8df75cf..b09a79f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,11 +3,6 @@ repos: rev: v8.24.2 hooks: - id: gitleaks - name: gitleaks (full scan on push) - stages: [pre-push] - args: ["detect", "--source", ".", "--no-banner"] - pass_filenames: false - always_run: true - repo: https://github.com/astral-sh/uv-pre-commit # uv version. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8fccd09..a7a1de1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -178,6 +178,202 @@ git commit -m "added package-name dependency" #### 5. Open a PR CI will validate that the lockfile and environment are consistent. If you forgot to update the lockfile, the PR will fail with a clear error. +--- + +## Type Safety Practices + +Python is a dynamically typed language. This flexibility makes Python productive and expressive, but it also increases the risk of subtle bugs caused by incorrect function calls, unexpected None values, or inconsistent data structures.To balance flexibility with long-term maintainability we use [Pyright](https://microsoft.github.io/pyright) for CI level type-checking. + +We run Pyright in `standard` mode. This mode provides strong type correctness guarantees without requiring the full strictness and annotation overhead of `strict` mode. + +You can check the exact type checking constraints enforced in `standard` mode here in the `Diagnostic Defaults` section of the [Pyright documentation](https://microsoft.github.io/pyright/#/configuration?id=diagnostic-settings-defaults). + +`standard` mode in Pyright is chosen because it enforces the following principles: + +- **Catch real bugs early** - It prevents incorrect function calls, invalid attribute access, misuse of Optional values, inconsistent overloads, and a wide range of type errors that would otherwise only appear at runtime. + +- **Maintain clarity without excessive annotation burden** - Developers are not expected to annotate every variable or build fully typed signatures for every function. Pyright uses inference aggressively, and `standard` mode focuses on correctness where types are known or inferred. + +- **Work seamlessly with third-party libraries** - Many Python libraries ship without type stubs. In `standard` mode, these imports are treated as Any, allowing us to use them without blocking type checks while still preserving type safety inside our own code. + +### Runtime Type Safety at System Boundaries + +While Pyright provides excellent static type checking during development, **system boundaries** require additional runtime validation. These are points where our Python code interfaces with external systems, user input, or network requests where data types cannot be guaranteed at compile time. + +In this project, we use **Pydantic** for rigorous runtime type checking at these critical handover points: + +#### FastAPI Endpoints +All FastAPI route handlers use Pydantic models for request/response validation: +- Request bodies are validated against Pydantic schemas +- Query parameters and path parameters are type-checked at runtime +- Response models ensure consistent API contract enforcement +```python +# Example: API endpoint with Pydantic validation +from pydantic import BaseModel +from fastapi import FastAPI + +class UserRequest(BaseModel): + name: str + age: int + +@app.post("/users") +async def create_user(user: UserRequest): + # Pydantic validates name is string, age is int + # Invalid data raises 422 before reaching this code + return {"id": 1, "name": user.name} +``` + +This dual approach of **static type checking with Pyright** + **runtime validation with Pydantic** ensures both development-time correctness and production-time reliability at system boundaries where type safety cannot be statically guaranteed. + +**Note: Type checks are only run on core source code and not on test-cases** + +## Linter Rules + +Consistent linting is essential for maintaining a reliable and scalable code-base. By adhering to a well-defined linter configuration, we ensure the code remains readable, secure, and predictable even as the project evolves. + +The following set of rules are enabled in this repository. Linter rules are enforced automatically through the CI pipeline and must pass before merging changes into the `wip`, `dev`, or `main` branches. +. + +Each category is summarized with a description and a link to the Ruff documentation explaining these rules. + +### Selected Linter Rule Categories + +#### E4, E7, E9 — Pycodestyle Error Rules + +These check for fundamental correctness issues such as import formatting, indentation, and syntax problems that would otherwise cause runtime failures. + +- **E4**: Import formatting and blank-line rules + (https://docs.astral.sh/ruff/rules/#pycodestyle-e4) + +- **E7**: Indentation and tab-related issues +(https://docs.astral.sh/ruff/rules/#pycodestyle-e7) + +- **E9**: Syntax errors and runtime error patterns (e.g., undefined names in certain contexts) +(https://docs.astral.sh/ruff/rules/#pycodestyle-e9) + +#### F — Pyflakes + +Static analysis rules that detect real bug patterns such as unused variables, unused imports, undefined names, duplicate definitions, and logical mistakes that can cause bugs. + +(https://docs.astral.sh/ruff/rules/#pyflakes-f) + +#### B — Flake8-Bugbear + +A set of high-value checks for common Python pitfalls: mutable default arguments, improper exception handling, unsafe patterns, redundant checks, and subtle bugs that impact correctness and security. + +(https://docs.astral.sh/ruff/rules/#flake8-bugbear-b) + +#### T20 — Flake8-Print + +Flags any usage of `print()` or `pprint()` in production code to prevent leaking sensitive information, mixing debug output into logs, or introducing uncontrolled console output. + +(https://docs.astral.sh/ruff/rules/#flake8-print-t20) + +#### N — PEP8-Naming + +Ensures consistent and conventional naming across classes, functions, variables, and modules. This helps maintain readability across the engineering team and reinforces clarity in code reviews. + +(https://docs.astral.sh/ruff/rules/#pep8-naming-n) + +#### ANN — Flake8-Annotations + +Enforces type annotation discipline across functions, methods, and class structures. With Pyright used for type checking, these rules ensure that type information remains explicit and complete. + +(https://docs.astral.sh/ruff/rules/#flake8-annotations-ann) + +#### ERA — Eradicate + +Removes or flags commented-out code fragments. Commented code tends to accumulate over time and reduces clarity. The goal is to keep the repository clean and avoid keeping dead code in version control. + +(https://docs.astral.sh/ruff/rules/#eradicate-era) + +#### PERF — Perflint + +Performance-oriented rules that highlight inefficient constructs, slow loops, unnecessary list or dict operations, and patterns that degrade runtime efficiency. + +(https://docs.astral.sh/ruff/rules/#perflint-perf) + +### Fixing Linting Issues + +Linting issues should always be resolved manually. +We **strongly discourage** relying on autofixes using `ruff check --fix` for this repository. + +Unlike `ruff format`, which performs safe and predictable code formatting, the linter's autofix mode can alter control flow, refactor logic, or rewrite expressions in ways that introduce unintended bugs. + +All linter errors will have **rule-code** like `ANN204` for example. +You can use the command line command +```bash +ruff rule #for example: ANN204 +``` + +to get an explanation on the rule code, why it's a problem and how you can fix it. + +Human oversight is essential to ensure that any corrective changes maintain the intended behavior of the application. Contributors should review each reported linting issue, understand why it is flagged, and apply the appropriate fix by hand. + +--- + +## Formatting Rules + +This repository uses the **Ruff Formatter** for code formatting. Its behavior is deterministic, safe, and aligned with the [Black Code Style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html). + +Formatting is enforced automatically through the CI pipeline and must pass before merging changes into the `wip`, `dev`, or `main` branches. + +### Selected Formatting Behaviors + +#### String Quote Style + +All string literals are formatted using **double quotes**. +This preserves consistency across the codebase and avoids unnecessary formatting churn. + +(https://docs.astral.sh/ruff/formatter/#quote-style) + +#### Indentation Style + +Indentation always uses **spaces, not tabs**. +This mirrors the formatting style adopted by Black and avoids ambiguity across editors and environments. + +(https://docs.astral.sh/ruff/formatter/#indent-style) + +#### Magic Trailing Commas + +The formatter respects magic trailing commas, meaning: + +- **Adding a trailing comma** in lists, dicts, tuples, or function calls will trigger multi-line formatting. +- **Removing a trailing comma** results in a more compact single-line layout where appropriate. + +This produces stable diffs and predictable wrapping behavior. + +(https://docs.astral.sh/ruff/formatter/#skip-magic-trailing-comma) + +#### Automatic Line Ending Detection + +Ruff automatically detects and preserves the correct line-ending style (LF or CRLF) based on the existing file. +This prevents accidental line-ending changes when multiple developers work on different systems. + +(https://docs.astral.sh/ruff/formatter/#line-ending) + +#### Docstring Code Blocks + +The formatter **does not reformat** code blocks inside docstrings. +This ensures that examples, snippets, API usage patterns, and documentation content remain exactly as written, preventing unintended modifications to teaching material or markdown-style fenced blocks. + +(https://docs.astral.sh/ruff/formatter/#docstring-code-format) + +### Applying Formatting + +Unlike lint autofixes, **formatting changes are safe by design**. +The formatter never changes logical behavior, control flow, or semantics. It only standardizes layout. + +You can run formatting locally using: + +```bash +uv run ruff format +``` + +All formatting issues must be resolved before creating a pull request or merging into protected branches. + + + --- ### Important Notes diff --git a/DSL/CronManager/DSL/data_resync.yml b/DSL/CronManager/DSL/data_resync.yml new file mode 100644 index 0000000..c5fb58d --- /dev/null +++ b/DSL/CronManager/DSL/data_resync.yml @@ -0,0 +1,5 @@ +agency_data_resync: + # trigger: "0 0/1 * * * ?" + trigger: off + type: exec + command: "../app/scripts/agency_data_resync.sh -s 10" \ No newline at end of file diff --git a/DSL/CronManager/DSL/delete_from_vault.yml b/DSL/CronManager/DSL/delete_from_vault.yml new file mode 100644 index 0000000..be20961 --- /dev/null +++ b/DSL/CronManager/DSL/delete_from_vault.yml @@ -0,0 +1,5 @@ +delete_secrets: + trigger: off + type: exec + command: "/app/scripts/delete_secrets_from_vault.sh" + allowedEnvs: ['cookie', 'connectionId','llmPlatform', 'llmModel','embeddingModel','embeddingPlatform','deploymentEnvironment'] diff --git a/DSL/CronManager/DSL/initiate_vector_indexer.yml b/DSL/CronManager/DSL/initiate_vector_indexer.yml new file mode 100644 index 0000000..561f787 --- /dev/null +++ b/DSL/CronManager/DSL/initiate_vector_indexer.yml @@ -0,0 +1,5 @@ +vector_indexer: + trigger: off + type: exec + command: "../app/scripts/vector_indexer_pipeline.sh" + allowedEnvs: ['signedUrl', 'clientDataHash'] \ No newline at end of file diff --git a/DSL/CronManager/DSL/reset.yml b/DSL/CronManager/DSL/reset.yml new file mode 100644 index 0000000..2e1d867 --- /dev/null +++ b/DSL/CronManager/DSL/reset.yml @@ -0,0 +1,5 @@ +reset_monthly_budget: + trigger: "0 0 1 * * ?" # Runs at 00:00 AM 1st day of every month + # trigger: off + type: exec + command: "../app/scripts/budget_reset.sh -s 10" diff --git a/DSL/CronManager/DSL/store_in_vault.yml b/DSL/CronManager/DSL/store_in_vault.yml new file mode 100644 index 0000000..3052219 --- /dev/null +++ b/DSL/CronManager/DSL/store_in_vault.yml @@ -0,0 +1,5 @@ +store_secrets: + trigger: off + type: exec + command: "/app/scripts/store_secrets_in_vault.sh" + allowedEnvs: ['cookie', 'connectionId','llmPlatform', 'llmModel','secretKey','accessKey','deploymentName','targetUrl','apiKey','embeddingModel','embeddingPlatform','embeddingAccessKey','embeddingSecretKey','embeddingDeploymentName','embeddingTargetUri','embeddingAzureApiKey','deploymentEnvironment'] \ No newline at end of file diff --git a/DSL/CronManager/config/config.ini b/DSL/CronManager/config/config.ini new file mode 100644 index 0000000..a154d8e --- /dev/null +++ b/DSL/CronManager/config/config.ini @@ -0,0 +1,3 @@ +[DSL] + +RAG_SEARCH_RESQL=http://resql:8082 diff --git a/DSL/CronManager/script/agency_data_resync.sh b/DSL/CronManager/script/agency_data_resync.sh new file mode 100644 index 0000000..33ae952 --- /dev/null +++ b/DSL/CronManager/script/agency_data_resync.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# DEFINING ENDPOINTS + +CHECK_RESYNC_DATA_AVAILABILITY_ENDPOINT=http://ruuter-public:8086/rag-search/data/update + +# Construct payload to update training status using cat +payload=$(cat < secret/data/path and secret/metadata/path) + local data_path=$(echo "$vault_path" | sed 's|^secret/|secret/data/|') + local metadata_path=$(echo "$vault_path" | sed 's|^secret/|secret/metadata/|') + + log "Data API URL: $VAULT_ADDR/v1/$data_path" + log "Metadata API URL: $VAULT_ADDR/v1/$metadata_path" + + local success=true + + # Delete secret data + log "Deleting secret data..." + local data_response=$(curl -s -w "HTTPSTATUS:%{http_code}" \ + -X DELETE \ + -H "X-Vault-Token: $VAULT_TOKEN" \ + "$VAULT_ADDR/v1/$data_path") + + local data_http_code=$(echo "$data_response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2) + local data_body=$(echo "$data_response" | sed -E 's/HTTPSTATUS:[0-9]*$//') + + if [[ "$data_http_code" -ge 200 && "$data_http_code" -lt 300 ]] || [[ "$data_http_code" == "404" ]]; then + log "Secret data deleted successfully (HTTP $data_http_code)" + else + log "WARNING: Failed to delete secret data (HTTP $data_http_code)" + log "Data response: $data_body" + success=false + fi + + # Delete secret metadata + log "Deleting secret metadata..." + local metadata_response=$(curl -s -w "HTTPSTATUS:%{http_code}" \ + -X DELETE \ + -H "X-Vault-Token: $VAULT_TOKEN" \ + "$VAULT_ADDR/v1/$metadata_path") + + local metadata_http_code=$(echo "$metadata_response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2) + local metadata_body=$(echo "$metadata_response" | sed -E 's/HTTPSTATUS:[0-9]*$//') + + if [[ "$metadata_http_code" -ge 200 && "$metadata_http_code" -lt 300 ]] || [[ "$metadata_http_code" == "404" ]]; then + log "Secret metadata deleted successfully (HTTP $metadata_http_code)" + else + log "WARNING: Failed to delete secret metadata (HTTP $metadata_http_code)" + log "Metadata response: $metadata_body" + success=false + fi + + if [ "$success" = true ]; then + log "$secret_description deletion completed successfully" + else + log "WARNING: $secret_description deletion completed with some failures" + fi + + return 0 # Continue even if some deletions fail +} + +# Function to delete LLM secrets +delete_llm_secrets() { + if [ -z "$llmPlatform" ] || [ -z "$llmModel" ]; then + log "No LLM platform or model specified, skipping LLM secrets deletion" + return 0 + fi + + local platform_name=$(get_platform_name "$llmPlatform") + local model_name=$(get_model_name "$llmModel") + local vault_path=$(build_vault_path "llm" "$platform_name" "$model_name") + + delete_vault_secret "$vault_path" "LLM secrets" +} + +# Function to delete embedding secrets +delete_embedding_secrets() { + if [ -z "$embeddingPlatform" ] || [ -z "$embeddingModel" ]; then + log "No embedding platform or model specified, skipping embedding secrets deletion" + return 0 + fi + + local platform_name=$(get_platform_name "$embeddingPlatform") + local vault_path=$(build_vault_path "embeddings" "$platform_name" "$embeddingModel") + + delete_vault_secret "$vault_path" "Embedding secrets" +} + +# Main execution +if [ -n "$llmPlatform" ]; then + log "LLM Platform: $(get_platform_name "$llmPlatform")" +fi + +if [ -n "$llmModel" ]; then + log "LLM Model: $(get_model_name "$llmModel")" +fi + +if [ -n "$embeddingPlatform" ]; then + log "Embedding Platform: $(get_platform_name "$embeddingPlatform")" +fi + +# Delete LLM secrets +delete_llm_secrets + +# Delete embedding secrets +delete_embedding_secrets + +log "=== Vault secrets deletion completed ===" diff --git a/DSL/CronManager/script/store_secrets_in_vault.sh b/DSL/CronManager/script/store_secrets_in_vault.sh new file mode 100644 index 0000000..dfc433b --- /dev/null +++ b/DSL/CronManager/script/store_secrets_in_vault.sh @@ -0,0 +1,320 @@ +#!/bin/bash + +# Vault Secrets Storage Script +# This script stores LLM and embedding credentials in HashiCorp Vault + +set -e # Exit on any error + +# Configuration +VAULT_ADDR="${VAULT_ADDR:-http://vault:8200}" +VAULT_TOKEN_FILE="/agent/out/token" + +# Logging function +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" +} + +log "=== Starting Vault Secrets Storage ===" + +# Debug: Print received parameters +log "Received parameters:" +log " connectionId: $connectionId" +log " llmPlatform: $llmPlatform" +log " llmModel: $llmModel" +log " deploymentEnvironment: $deploymentEnvironment" + +# Read vault token +if [ ! -f "$VAULT_TOKEN_FILE" ]; then + log "ERROR: Vault token file not found at $VAULT_TOKEN_FILE" + exit 1 +fi + +VAULT_TOKEN=$(cat "$VAULT_TOKEN_FILE") +if [ -z "$VAULT_TOKEN" ]; then + log "ERROR: Vault token is empty" + exit 1 +fi + +log "Vault token loaded successfully" + +# Function to determine platform name +get_platform_name() { + case "$llmPlatform" in + "aws") echo "aws_bedrock" ;; + "azure") echo "azure_openai" ;; + *) + log "ERROR: Unsupported platform: $llmPlatform" + exit 1 + ;; + esac +} + +# Function to get model name (first element from array) +get_model_name() { + # Remove brackets and quotes, get first element + echo "$llmModel" | sed 's/\[//g' | sed 's/\]//g' | sed 's/"//g' | cut -d',' -f1 | xargs +} + +# Function to build vault path +build_vault_path() { + local secret_type=$1 # "llm" or "embeddings" + local platform=$(get_platform_name) + + # Use appropriate model based on secret type + local model + if [ "$secret_type" = "embeddings" ]; then + model="$embeddingModel" + else + model=$(get_model_name) + fi + + if [ "$deploymentEnvironment" = "testing" ]; then + echo "secret/$secret_type/connections/$platform/$deploymentEnvironment/$connectionId" + else + echo "secret/$secret_type/connections/$platform/$deploymentEnvironment/$model" + fi +} + +# Function to store LLM secrets +store_llm_secrets() { + local vault_path=$(build_vault_path "llm") + log "Storing LLM secrets at path: $vault_path" + + case "$llmPlatform" in + "aws") + store_aws_llm_secrets "$vault_path" + ;; + "azure") + store_azure_llm_secrets "$vault_path" + ;; + esac +} + +# Function to store embedding secrets +store_embedding_secrets() { + local vault_path=$(build_vault_path "embeddings") + log "Storing embedding secrets at path: $vault_path" + + case "$embeddingPlatform" in + "aws") + store_aws_embedding_secrets "$vault_path" + ;; + "azure") + store_azure_embedding_secrets "$vault_path" + ;; + *) + log "WARNING: Embedding platform '$embeddingPlatform' not supported, skipping embedding secrets" + ;; + esac +} + +# Function to store AWS LLM secrets +store_aws_llm_secrets() { + local vault_path=$1 + local model=$(get_model_name) + + log "Storing AWS LLM secrets..." + + # Build JSON payload + local json_payload=$(cat < secret/data/path) + local api_path=$(echo "$vault_path" | sed 's|^secret/|secret/data/|') + log "API URL: $VAULT_ADDR/v1/$api_path" + + # Execute HTTP API call + local response=$(curl -s -w "HTTPSTATUS:%{http_code}" \ + -X POST \ + -H "X-Vault-Token: $VAULT_TOKEN" \ + -H "Content-Type: application/json" \ + -d "$json_payload" \ + "$VAULT_ADDR/v1/$api_path") + + local http_code=$(echo "$response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2) + local body=$(echo "$response" | sed -E 's/HTTPSTATUS:[0-9]*$//') + + if [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]]; then + log "AWS LLM secrets stored successfully (HTTP $http_code)" + else + log "ERROR: Failed to store AWS LLM secrets (HTTP $http_code)" + log "Response: $body" + exit 1 + fi +} + +# Function to store Azure LLM secrets +store_azure_llm_secrets() { + local vault_path=$1 + local model=$(get_model_name) + + log "Storing Azure LLM secrets..." + + # Build JSON payload + local json_payload=$(cat < secret/data/path) + local api_path=$(echo "$vault_path" | sed 's|^secret/|secret/data/|') + log "API URL: $VAULT_ADDR/v1/$api_path" + + # Execute HTTP API call + local response=$(curl -s -w "HTTPSTATUS:%{http_code}" \ + -X POST \ + -H "X-Vault-Token: $VAULT_TOKEN" \ + -H "Content-Type: application/json" \ + -d "$json_payload" \ + "$VAULT_ADDR/v1/$api_path") + + local http_code=$(echo "$response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2) + local body=$(echo "$response" | sed -E 's/HTTPSTATUS:[0-9]*$//') + + if [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]]; then + log "Azure LLM secrets stored successfully (HTTP $http_code)" + else + log "ERROR: Failed to store Azure LLM secrets (HTTP $http_code)" + log "Response: $body" + exit 1 + fi +} + +# Function to store AWS embedding secrets +store_aws_embedding_secrets() { + local vault_path=$1 + + log "Storing AWS embedding secrets..." + + # Build JSON payload + local json_payload=$(cat < secret/data/path) + local api_path=$(echo "$vault_path" | sed 's|^secret/|secret/data/|') + log "API URL: $VAULT_ADDR/v1/$api_path" + + # Execute HTTP API call + local response=$(curl -s -w "HTTPSTATUS:%{http_code}" \ + -X POST \ + -H "X-Vault-Token: $VAULT_TOKEN" \ + -H "Content-Type: application/json" \ + -d "$json_payload" \ + "$VAULT_ADDR/v1/$api_path") + + local http_code=$(echo "$response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2) + local body=$(echo "$response" | sed -E 's/HTTPSTATUS:[0-9]*$//') + + if [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]]; then + log "AWS embedding secrets stored successfully (HTTP $http_code)" + else + log "ERROR: Failed to store AWS embedding secrets (HTTP $http_code)" + log "Response: $body" + exit 1 + fi +} + +# Function to store Azure embedding secrets +store_azure_embedding_secrets() { + local vault_path=$1 + + log "Storing Azure embedding secrets..." + + # Build JSON payload + local json_payload=$(cat < secret/data/path) + local api_path=$(echo "$vault_path" | sed 's|^secret/|secret/data/|') + log "API URL: $VAULT_ADDR/v1/$api_path" + + # Execute HTTP API call + local response=$(curl -s -w "HTTPSTATUS:%{http_code}" \ + -X POST \ + -H "X-Vault-Token: $VAULT_TOKEN" \ + -H "Content-Type: application/json" \ + -d "$json_payload" \ + "$VAULT_ADDR/v1/$api_path") + + local http_code=$(echo "$response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2) + local body=$(echo "$response" | sed -E 's/HTTPSTATUS:[0-9]*$//') + + if [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]]; then + log "Azure embedding secrets stored successfully (HTTP $http_code)" + else + log "ERROR: Failed to store Azure embedding secrets (HTTP $http_code)" + log "Response: $body" + exit 1 + fi +} + +# Main execution +log "Platform: $(get_platform_name)" +log "Model: $(get_model_name)" + +# Store LLM secrets +store_llm_secrets + +# Store embedding secrets if embedding platform is provided +if [ -n "$embeddingPlatform" ]; then + store_embedding_secrets +else + log "No embedding platform specified, skipping embedding secrets" +fi + +log "=== Vault secrets storage completed successfully ===" + diff --git a/DSL/CronManager/script/vector_indexer_pipeline.sh b/DSL/CronManager/script/vector_indexer_pipeline.sh new file mode 100644 index 0000000..035179a --- /dev/null +++ b/DSL/CronManager/script/vector_indexer_pipeline.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +echo "Starting vector indexer pipeline..." + +if [ -z "$signedUrl" ] || [ -z "$clientDataHash" ]; then + echo "Please set the signedUrl and clientDataHash environment variables." + exit 1 +fi + +PYTHON_SCRIPT="/app/src/vector_indexer/main_indexer.py" + +echo "Using signedUrl: $signedUrl" +echo "Using clientDataHash: $clientDataHash" + +# Install uv if not found +UV_BIN="/root/.local/bin/uv" +if [ ! -f "$UV_BIN" ]; then + echo "[UV] Installing uv..." + curl -LsSf https://astral.sh/uv/install.sh | sh || { + echo "[ERROR] Failed to install uv" + exit 1 + } +fi + +# Activate Python virtual environment +VENV_PATH="/app/python_virtual_env" +echo "[VENV] Activating virtual environment at: $VENV_PATH" +source "$VENV_PATH/bin/activate" || { + echo "[ERROR] Failed to activate virtual environment" + exit 1 +} + +# Install required packages +echo "[PACKAGES] Installing required packages..." + +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "numpy>=1.21.0,<2.0" || exit 1 +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "requests>=2.32.5" || exit 1 +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "pydantic>=2.11.7" || exit 1 +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "qdrant-client>=1.15.1" || exit 1 +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "rank-bm25>=0.2.2" || exit 1 +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "tiktoken>=0.11.0" || exit 1 +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "dvc[s3]>=3.55.2" || exit 1 +"$UV_BIN" pip install --python "$VENV_PATH/bin/python3" "loguru>=0.7.3" || exit 1 + +echo "[PACKAGES] All packages installed successfully" + +export PYTHONPATH="/app:/app/src:/app/src/vector_indexer:$PYTHONPATH" + +[ ! -f "$PYTHON_SCRIPT" ] && { echo "[ERROR] Python script not found"; exit 1; } + +echo "[FOUND] Python script at: $PYTHON_SCRIPT" + +# Run vector indexer with signed URL parameter +echo "[STARTING] Vector indexer processing..." + +echo "[DEBUG] About to execute main_indexer.py..." +if [ -n "$signedUrl" ]; then + echo "[SIGNED_URL] Using signed URL for dataset processing" + echo "[COMMAND] python3 -u $PYTHON_SCRIPT --signed-url $signedUrl" + python3 -u "$PYTHON_SCRIPT" --signed-url "$signedUrl" 2>&1 + PYTHON_EXIT_CODE=$? +else + echo "[NO_URL] Running without signed URL" + echo "[COMMAND] python3 -u $PYTHON_SCRIPT" + python3 -u "$PYTHON_SCRIPT" 2>&1 + PYTHON_EXIT_CODE=$? +fi + +echo "[DEBUG] Python execution completed with exit code: $PYTHON_EXIT_CODE" + +# Handle exit codes +if [ $PYTHON_EXIT_CODE -eq 0 ]; then + echo "[SUCCESS] Vector indexer completed successfully" + exit 0 +elif [ $PYTHON_EXIT_CODE -eq 2 ]; then + echo "[WARNING] Vector indexer completed with some failures" + exit 2 +elif [ $PYTHON_EXIT_CODE -eq 130 ]; then + echo "[INTERRUPTED] Vector indexer was interrupted by user" + exit 130 +else + echo "[ERROR] Vector indexer failed with exit code: $PYTHON_EXIT_CODE" + exit $PYTHON_EXIT_CODE +fi \ No newline at end of file diff --git a/DSL/DMapper/rag-search/lib/helpers.js b/DSL/DMapper/rag-search/lib/helpers.js new file mode 100644 index 0000000..6f5e74f --- /dev/null +++ b/DSL/DMapper/rag-search/lib/helpers.js @@ -0,0 +1,271 @@ +import { randomBytes } from "crypto"; +import fs from "fs/promises"; +import path from "path"; + +export function getAuthHeader(username, token) { + const auth = `${username}:${token}`; + const encodedAuth = Buffer.from(auth).toString("base64"); + return `Basic ${encodedAuth}`; +} + +export function mergeLabelData(labels, existing_labels) { + let mergedArray = [...labels, ...existing_labels]; + let uniqueArray = [...new Set(mergedArray)]; + return { labels: uniqueArray }; +} + +export function platformStatus(platform, data) { + const platformData = data.find((item) => item.platform === platform); + return platformData ? platformData.isConnect : false; +} + +export function isLabelsMismatch(newLabels, correctedLabels, predictedLabels) { + function check(arr, newLabels) { + if ( + Array.isArray(newLabels) && + Array.isArray(arr) && + newLabels.length === arr.length + ) { + for (let label of newLabels) { + if (!arr.includes(label)) { + return true; + } + } + return false; + } else { + return true; + } + } + + const val1 = check(correctedLabels, newLabels); + const val2 = check(predictedLabels, newLabels); + return val1 && val2; +} + +export function getOutlookExpirationDateTime() { + const currentDate = new Date(); + currentDate.setDate(currentDate.getDate() + 3); + const updatedDateISOString = currentDate.toISOString(); + return updatedDateISOString; +} + +export function findDuplicateStopWords(inputArray, existingArray) { + const set1 = new Set(existingArray); + const duplicates = inputArray.filter((item) => set1.has(item)); + const value = JSON.stringify(duplicates); + return value; +} + +export function findNotExistingStopWords(inputArray, existingArray) { + const set1 = new Set(existingArray); + const notExisting = inputArray.filter((item) => !set1.has(item)); + const value = JSON.stringify(notExisting); + return value; +} + +export function getRandomString() { + const randomHexString = randomBytes(32).toString("hex"); + return randomHexString; +} + +export function base64Decrypt(cipher, isObject) { + if (!cipher) { + return JSON.stringify({ + error: true, + message: 'Cipher is missing', + }); + } + + try { + const decodedContent = !isObject ? Buffer.from(cipher, 'base64').toString('utf8') : JSON.parse(Buffer.from(cipher, 'base64').toString('utf8')); + const cleanedContent = decodedContent.replace(/\r/g, ''); + return JSON.stringify({ + error: false, + content: cleanedContent + }); + } catch (err) { + return JSON.stringify({ + error: true, + message: 'Base64 Decryption Failed', + }); + } +} + +export function base64Encrypt(content) { + if (!content) { + return { + error: true, + message: 'Content is missing', + } + } + + try { + return JSON.stringify({ + error: false, + cipher: Buffer.from(typeof content === 'string' ? content : JSON.stringify(content)).toString('base64') + }); + } catch (err) { + return JSON.stringify({ + error: true, + message: 'Base64 Encryption Failed', + }); + } +} + +export function jsEscape(str) { + return JSON.stringify(str).slice(1, -1) +} + +export function isValidIntentName(name) { + // Allows letters (any unicode letter), numbers, and underscores + // Matches front-end validation with spaces replaced with underscores + return /^[\p{L}\p{N}_]+$/u.test(name); +} + +export function eq(v1, v2) { + return v1 === v2; +} + +export function getAgencyDataHash(agencyId) { + // Generate a random hash based on agency ID + // Create a consistent but seemingly random hash for each agencyId + const baseHash = agencyId.padEnd(10, agencyId); // Ensure at least 10 chars + let hash = ''; + const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; + + // Use the agencyId as a seed for pseudo-randomness + for (let i = 0; i < 16; i++) { + // Get character code from the baseHash, or use index if out of bounds + const charCode = i < baseHash.length ? baseHash.charCodeAt(i) : i; + // Use the character code to get an index in our chars string + const index = (charCode * 13 + i * 7) % chars.length; + hash += chars[index]; + } + + return hash; +} + +export function getAgencyDataAvailable(agencyId) { + // Use agencyId as a seed for deterministic but seemingly random result + // This ensures the same agencyId always gets the same result in the same session + + // Create a hash from the agencyId + let hashValue = 0; + for (let i = 0; i < agencyId.length; i++) { + hashValue = ((hashValue << 5) - hashValue) + agencyId.charCodeAt(i); + hashValue |= 0; // Convert to 32bit integer + } + + // Add a time component to make it change between sessions + // Use current date (year+month only) so it changes monthly but not every request + const date = new Date(); + const timeComponent = date.getFullYear() * 100 + date.getMonth(); + + // Combine the hash and time component for pseudo-randomness + const combinedValue = hashValue + timeComponent; + + // Return true or false based on even/odd value + return (combinedValue % 2) === 0; +} + +export function json(context) { + return JSON.stringify(context); +} + +/** + * Helper function to check if a value is an array + * @param {any} value - The value to check + * @returns {boolean} - True if value is an array, false otherwise + */ +export function isArray(value) { + return Array.isArray(value); +} + +/** + * Returns an array of agencies that are in centopsAgencies but not in gcAgencies (by agencyId). + * @param {Array} gcAgencies - Array of existing agencies, each with an agencyId property. + * @param {Array} centopsAgencies - Array of agencies from CentOps, each with an agencyId property. + * @returns {Array} Array of new agency objects from centopsAgencies. + */ +export function extractNewAgencies(gcAgencies, centopsAgencies) { + const existingIds = new Set(gcAgencies.map(a => a.agencyId)); + const newAgencies = centopsAgencies.filter(a => !existingIds.has(a.agencyId)) + // return newAgencies; + return JSON.stringify({ + agencies: newAgencies, + }); +} + +/** + * Downloads a JSON file from S3 and returns its parsed content. + * @param {string} datasetId + * @param {string|number} pageNum + * @returns {Object} Parsed JSON content of the file + */ +export function getSingleChunkData(chunkData) { + const mapped = chunkData?.map(item => ({ + clientId: item.agency_id, + id: item.id, + clientName: item.agency_name, + question: item.question + })); + + return JSON.stringify(mapped); +} + +export function getPaginatedChunkIds(chunks, agencyId, pageNum, pageSize = 5) { + let agencyRecordIndex = 0; // total agency records seen so far + let collected = 0; // agency records collected for this page + let resultChunks = []; + let startIndex = 0; + let foundPage = false; + + for (const chunk of chunks) { + let agencies = JSON.parse(chunk.includedAgencies.value) + + const count = agencies.filter(a => String(a) === String(agencyId)).length; + if (count === 0) continue; + + // If we haven't reached the start of this page, skip these records + if (!foundPage && agencyRecordIndex + count < (pageNum - 1) * pageSize + 1) { + agencyRecordIndex += count; + continue; + } + + // If this is the first chunk of the page, calculate startIndex + if (!foundPage) { + startIndex = (pageNum - 1) * pageSize - agencyRecordIndex; + foundPage = true; + } + + resultChunks.push(chunk.chunkId || chunk.chunkId); + collected += count; + + if (collected >= pageSize) break; + + agencyRecordIndex += count; + } + + return JSON.stringify( + { + chunks: resultChunks, + startIndex: startIndex + } + ); +} + +export function filterDataByAgency(aggregatedData, startIndex, agencyId, pageSize=5) { + + const filtered = aggregatedData.filter(item => String(item.agency_id) === String(agencyId)); + + const paginated = filtered.slice(startIndex, startIndex + 5); + + const result= paginated.map(item => ({ + clientId: item.agency_id, + id: item.id, + clientName: item.agency_name, // No mapping available, so use agency_id + question: item.question + })); + return JSON.stringify(result); + +} diff --git a/DSL/DMapper/rag-search/lib/requestLoggerMiddleware.js b/DSL/DMapper/rag-search/lib/requestLoggerMiddleware.js new file mode 100644 index 0000000..727a36f --- /dev/null +++ b/DSL/DMapper/rag-search/lib/requestLoggerMiddleware.js @@ -0,0 +1,30 @@ +/** + * @param res Original Response Object + * @param send Original UNMODIFIED res.send function + * @return A patched res.send which takes the send content, binds it to contentBody on + * the res and then calls the original res.send after restoring it + */ +const resDotSendInterceptor = (res, send) => (content) => { + res.contentBody = content; + res.send = send; + res.send(content); +}; + +export const requestLoggerMiddleware = + ({ logger }) => + (req, res, next) => { + logger( + `Request: {method: ${req.method}, url: ${ + req.url + }, params: ${JSON.stringify(req.params)}, query: ${JSON.stringify( + req.query + )}, body: ${JSON.stringify(req.body)}` + ); + res.send = resDotSendInterceptor(res, res.send); + res.on("finish", () => { + logger( + `Response: {statusCode: ${res.statusCode}, responseData: ${res.contentBody}}` + ); + }); + next(); + }; diff --git a/DSL/Liquibase/changelog/rag-search-script-v1-llm-connections.sql b/DSL/Liquibase/changelog/rag-search-script-v1-llm-connections.sql new file mode 100644 index 0000000..6367462 --- /dev/null +++ b/DSL/Liquibase/changelog/rag-search-script-v1-llm-connections.sql @@ -0,0 +1,141 @@ +-- Schema for LLM Connections +CREATE TABLE llm_connections ( + -- Metadata + id SERIAL PRIMARY KEY, + connection_name VARCHAR(255) NOT NULL DEFAULT '', + connection_status VARCHAR(50) DEFAULT 'active', -- active / inactive + created_at TIMESTAMP DEFAULT NOW(), + environment VARCHAR(50) NOT NULL, + + -- LLM Model Configuration + llm_platform VARCHAR(100) NOT NULL, -- e.g. Azure AI, OpenAI + llm_model VARCHAR(100) NOT NULL, -- e.g. GPT-4o + -- Azure + deployment_name VARCHAR(150), -- for Azure deployments + target_uri TEXT, -- for custom endpoints + api_key TEXT, -- secured api key mocked here + -- AWS Bedrock + secret_key TEXT, + access_key TEXT, + + -- Embedding Model Configuration + embedding_platform VARCHAR(100) NOT NULL, -- e.g. Azure AI, OpenAI + embedding_model VARCHAR(100) NOT NULL, -- e.g. Ada-200-1 + -- Azure + embedding_deployment_name VARCHAR(150), -- for Azure deployments + embedding_target_uri TEXT, -- for custom endpoints + embedding_azure_api_key TEXT, -- secured api key mocked here + -- AWS Bedrock + embedding_secret_key TEXT, + embedding_access_key TEXT, + + -- Budget and Usage Tracking + monthly_budget NUMERIC(12,2) NOT NULL, -- e.g. 1000.00 + used_budget NUMERIC(12,2) DEFAULT 0.00, -- e.g. 250.00 + warn_budget_threshold NUMERIC(5) DEFAULT 80, -- percentage to warn at + stop_budget_threshold NUMERIC(5) DEFAULT 100, -- percentage to stop at + disconnect_on_budget_exceed BOOLEAN DEFAULT TRUE +); + +CREATE TABLE inference_results ( + id SERIAL PRIMARY KEY, + llm_connection_id INT REFERENCES llm_connections(id) ON DELETE CASCADE, + chat_id TEXT, -- optional chat session ID + user_question TEXT NOT NULL, -- raw user input + refined_questions JSONB, -- list of refined questions (LLM-generated) + conversation_history JSONB, -- prior messages (array of {role, content}) + ranked_chunks JSONB, -- retrieved chunks (ranked, with metadata) + embedding_scores JSONB, -- distance scores for each chunk + final_answer TEXT, -- LLM’s final generated answer + environment TEXT, + created_at TIMESTAMP DEFAULT NOW() +); + +CREATE TABLE inference_results_references ( + id SERIAL PRIMARY KEY, + conversation_id INT NOT NULL REFERENCES inference_results(id) ON DELETE CASCADE, + reference_url TEXT NOT NULL +); + +-- Schema for Platform and Model Management + +-- Table for LLM Platforms +CREATE TABLE llm_platforms ( + id SERIAL PRIMARY KEY, + platform_key VARCHAR(50) NOT NULL UNIQUE, -- e.g., 'azure', 'aws' + platform_name VARCHAR(100) NOT NULL -- e.g., 'Azure OpenAI', 'AWS Bedrock' +); + +-- Table for LLM Models +CREATE TABLE llm_models ( + id SERIAL PRIMARY KEY, + platform_id INT NOT NULL REFERENCES llm_platforms(id) ON DELETE CASCADE, + model_key VARCHAR(100) NOT NULL, -- e.g., 'gpt-4o', 'anthropic-claude-3.5-sonnet' + model_name VARCHAR(150) NOT NULL, -- e.g., 'GPT-4o', 'Anthropic Claude 3.5 Sonnet' + UNIQUE(platform_id, model_key) +); + +-- Table for Embedding Platforms +CREATE TABLE embedding_platforms ( + id SERIAL PRIMARY KEY, + platform_key VARCHAR(50) NOT NULL UNIQUE, -- e.g., 'azure', 'aws' + platform_name VARCHAR(100) NOT NULL -- e.g., 'Azure OpenAI', 'AWS Bedrock' + +); + +-- Table for Embedding Models +CREATE TABLE embedding_models ( + id SERIAL PRIMARY KEY, + platform_id INT NOT NULL REFERENCES embedding_platforms(id) ON DELETE CASCADE, + model_key VARCHAR(100) NOT NULL, -- e.g., 'text-embedding-3-large', 'amazon.titan-embed-text-v2:0' + model_name VARCHAR(150) NOT NULL, -- e.g., 'text-embedding-3-large', 'Amazon Titan Text Embeddings V2' + UNIQUE(platform_id, model_key) +); + +-- Insert initial LLM platforms +INSERT INTO llm_platforms (platform_key, platform_name) VALUES +('azure', 'Azure OpenAI'), +('aws', 'AWS Bedrock'); + +-- Insert initial LLM models +INSERT INTO llm_models (platform_id, model_key, model_name) VALUES +-- Azure models +((SELECT id FROM llm_platforms WHERE platform_key = 'azure'), 'gpt-4o-mini', 'GPT-4o-mini'), +((SELECT id FROM llm_platforms WHERE platform_key = 'azure'), 'gpt-4o', 'GPT-4o'), +-- AWS models +((SELECT id FROM llm_platforms WHERE platform_key = 'aws'), 'anthropic-claude-3.5-sonnet', 'Anthropic Claude 3.5 Sonnet'), +((SELECT id FROM llm_platforms WHERE platform_key = 'aws'), 'anthropic-claude-3.7-sonnet', 'Anthropic Claude 3.7 Sonnet'); + +-- Insert initial embedding platforms +INSERT INTO embedding_platforms (platform_key, platform_name) VALUES +('azure', 'Azure OpenAI'), +('aws', 'AWS Bedrock'); + +-- Insert initial embedding models +INSERT INTO embedding_models (platform_id, model_key, model_name) VALUES +-- Azure embedding models +((SELECT id FROM embedding_platforms WHERE platform_key = 'azure'), 'text-embedding-3-large', 'text-embedding-3-large'), +-- AWS embedding models +((SELECT id FROM embedding_platforms WHERE platform_key = 'aws'), 'amazon.titan-embed-text-v2:0', 'Amazon Titan Text Embeddings V2'); + +-- Add indexes for better performance +CREATE INDEX idx_llm_models_platform_id ON llm_models(platform_id); +CREATE INDEX idx_embedding_models_platform_id ON embedding_models(platform_id); + +CREATE TABLE public.agency_sync ( + agency_id VARCHAR(50) PRIMARY KEY, + agency_data_hash VARCHAR(255), + data_url TEXT, + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP NOT NULL DEFAULT NOW() +); + +INSERT INTO public.agency_sync (agency_id, created_at) VALUES +('AGENCY001', NOW()); + +CREATE TABLE public.mock_ckb ( + client_id VARCHAR(50) PRIMARY KEY, + client_data_hash VARCHAR(255) NOT NULL, + signed_s3_url TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT NOW() +); \ No newline at end of file diff --git a/DSL/Liquibase/changelog/rag-search-script-v2-user-management.sql b/DSL/Liquibase/changelog/rag-search-script-v2-user-management.sql new file mode 100644 index 0000000..f47656b --- /dev/null +++ b/DSL/Liquibase/changelog/rag-search-script-v2-user-management.sql @@ -0,0 +1,41 @@ +-- liquibase formatted sql + +-- changeset Erangi Ariyasena:classifier-script-v3-changeset1 +CREATE TYPE user_status AS ENUM ('active','deleted'); + +-- changeset Erangi Ariyasena:classifier-script-v3-changeset2 +CREATE TABLE public."user" ( + id int8 NOT NULL GENERATED BY DEFAULT AS IDENTITY, + login VARCHAR(50) NOT NULL, + password_hash VARCHAR(60), + first_name VARCHAR(50), + last_name VARCHAR(50), + id_code VARCHAR(50) NOT NULL, + display_name VARCHAR(50), + status user_status, + csa_title VARCHAR, + csa_email VARCHAR, + created TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT user_pkey PRIMARY KEY (id) +); + +CREATE TABLE public."authority" ( + name VARCHAR(50) PRIMARY KEY +); + +CREATE TABLE public."user_authority" ( + id int8 NOT NULL GENERATED BY DEFAULT AS IDENTITY, + user_id VARCHAR(50) NOT NULL, + authority_name VARCHAR[] NOT NULL, + created TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT user_authority_pkey PRIMARY KEY (id) +); + +-- changeset Erangi Ariyasena:classifier-script-v1-changeset3 + +INSERT INTO public."user" (login,password_hash,first_name,last_name,id_code,display_name,status,csa_title,csa_email) +VALUES ('EE30303039914','ok','classifier','test','EE30303039914','classifier','active','Title','classifier.doe@example.com'); + +INSERT INTO public."user_authority" ( user_id, authority_name) +VALUES ('EE30303039914', ARRAY['ROLE_ADMINISTRATOR', 'ROLE_MODEL_TRAINER'] ); + diff --git a/DSL/Liquibase/changelog/rag-search-script-v3-configuration.sql b/DSL/Liquibase/changelog/rag-search-script-v3-configuration.sql new file mode 100644 index 0000000..cda1bb5 --- /dev/null +++ b/DSL/Liquibase/changelog/rag-search-script-v3-configuration.sql @@ -0,0 +1,15 @@ +-- liquibase formatted sql + +-- changeset Erangi Ariyasena:classifier-script-v5-changeset1 +CREATE TABLE public.configuration ( + id BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY, + key VARCHAR(128), + value VARCHAR(128), + created TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + deleted BOOLEAN NOT NULL DEFAULT FALSE, + CONSTRAINT configuration_pkey PRIMARY KEY (id) +); + +-- changeset Erangi Ariyasena:classifier-script-v5-changeset2 +INSERT INTO public.configuration (key, value) +VALUES ('session_length', '120'); diff --git a/DSL/Liquibase/changelog/rag-search-script-v4-authority-data.xml b/DSL/Liquibase/changelog/rag-search-script-v4-authority-data.xml new file mode 100644 index 0000000..f15c3d1 --- /dev/null +++ b/DSL/Liquibase/changelog/rag-search-script-v4-authority-data.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/DSL/Liquibase/data/authority.csv b/DSL/Liquibase/data/authority.csv new file mode 100644 index 0000000..c110c60 --- /dev/null +++ b/DSL/Liquibase/data/authority.csv @@ -0,0 +1,3 @@ +name +ROLE_ADMINISTRATOR +ROLE_MODEL_TRAINER diff --git a/DSL/Liquibase/liquibase.properties b/DSL/Liquibase/liquibase.properties new file mode 100644 index 0000000..0c4a6ff --- /dev/null +++ b/DSL/Liquibase/liquibase.properties @@ -0,0 +1,6 @@ +changelogFile: /changelog/master.yml +url: jdbc:postgresql://localhost:5436/rag-search +username: postgres +password: dbadmin +secureParsing: false +liquibase.hub.mode=off diff --git a/DSL/Liquibase/master.yml b/DSL/Liquibase/master.yml new file mode 100644 index 0000000..a1c31eb --- /dev/null +++ b/DSL/Liquibase/master.yml @@ -0,0 +1,9 @@ +databaseChangeLog: + - include: + file: changelog/rag-search-script-v1-llm-connections.sql + - include: + file: changelog/rag-search-script-v2-user-management.sql + - include: + file: changelog/rag-search-script-v3-configuration.sql + - include: + file: changelog/rag-search-script-v4-authority-data.xml \ No newline at end of file diff --git a/DSL/Resql/rag-search/GET/empty.sql b/DSL/Resql/rag-search/GET/empty.sql new file mode 100644 index 0000000..c53c239 --- /dev/null +++ b/DSL/Resql/rag-search/GET/empty.sql @@ -0,0 +1,2 @@ +-- This is a empty sql for Buerokratt DSL delivery method +SELECT current_date; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/deactivate-llm-connection-budget-exceed.sql b/DSL/Resql/rag-search/POST/deactivate-llm-connection-budget-exceed.sql new file mode 100644 index 0000000..af9da1b --- /dev/null +++ b/DSL/Resql/rag-search/POST/deactivate-llm-connection-budget-exceed.sql @@ -0,0 +1,11 @@ +UPDATE llm_connections +SET + connection_status = 'inactive' +WHERE id = :connection_id +RETURNING + id, + connection_name, + connection_status, + used_budget, + stop_budget_threshold, + disconnect_on_budget_exceed; diff --git a/DSL/Resql/rag-search/POST/delete-llm-connection.sql b/DSL/Resql/rag-search/POST/delete-llm-connection.sql new file mode 100644 index 0000000..ca50c8f --- /dev/null +++ b/DSL/Resql/rag-search/POST/delete-llm-connection.sql @@ -0,0 +1,2 @@ +DELETE FROM llm_connections +WHERE id = :connection_id; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/delete-user.sql b/DSL/Resql/rag-search/POST/delete-user.sql new file mode 100644 index 0000000..eb8ccad --- /dev/null +++ b/DSL/Resql/rag-search/POST/delete-user.sql @@ -0,0 +1,36 @@ +WITH active_administrators AS (SELECT user_id + FROM user_authority + WHERE 'ROLE_ADMINISTRATOR' = ANY (authority_name) + AND id IN (SELECT max(id) + FROM user_authority + GROUP BY user_id)), +delete_user AS ( +INSERT +INTO "user" (login, password_hash, first_name, last_name, id_code, display_name, status, created, csa_title, csa_email) +SELECT login, + password_hash, + first_name, + last_name, + id_code, + display_name, + 'deleted', + :created::timestamp with time zone, + csa_title, + csa_email +FROM "user" +WHERE id_code = :userIdCode + AND status <> 'deleted' + AND id IN (SELECT max(id) FROM "user" WHERE id_code = :userIdCode) + AND (1 < (SELECT COUNT(user_id) FROM active_administrators) + OR (1 = (SELECT COUNT(user_id) FROM active_administrators) + AND :userIdCode NOT IN (SELECT user_id FROM active_administrators)))), +delete_authority AS ( +INSERT +INTO user_authority (user_id, authority_name, created) +SELECT :userIdCode as users, ARRAY []::varchar[], :created::timestamp with time zone +FROM user_authority +WHERE 1 < (SELECT COUNT(user_id) FROM active_administrators) + OR (1 = (SELECT COUNT(user_id) FROM active_administrators) + AND :userIdCode NOT IN (SELECT user_id FROM active_administrators)) +GROUP BY users) +SELECT max(status) FROM "user" WHERE id_code = :userIdCode; diff --git a/DSL/Resql/rag-search/POST/get-agency-id.sql b/DSL/Resql/rag-search/POST/get-agency-id.sql new file mode 100644 index 0000000..a2bf5b0 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-agency-id.sql @@ -0,0 +1,4 @@ +SELECT + agency_id, + agency_data_hash +FROM public.agency_sync; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-configuration.sql b/DSL/Resql/rag-search/POST/get-configuration.sql new file mode 100644 index 0000000..f03b322 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-configuration.sql @@ -0,0 +1,5 @@ +SELECT id, key, value +FROM configuration +WHERE key=:key +AND id IN (SELECT max(id) from configuration GROUP BY key) +AND NOT deleted; diff --git a/DSL/Resql/rag-search/POST/get-embedding-models-by-platform.sql b/DSL/Resql/rag-search/POST/get-embedding-models-by-platform.sql new file mode 100644 index 0000000..c0968e5 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-embedding-models-by-platform.sql @@ -0,0 +1,11 @@ +SELECT + em.id, + em.model_key as value, + em.model_name as label, + em.platform_id, + ep.platform_key, + ep.platform_name +FROM embedding_models em +JOIN embedding_platforms ep ON em.platform_id = ep.id +WHERE (:embedding_platform_key IS NULL OR ep.platform_key = :embedding_platform_key) +ORDER BY em.model_name; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-embedding-platforms.sql b/DSL/Resql/rag-search/POST/get-embedding-platforms.sql new file mode 100644 index 0000000..9c90513 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-embedding-platforms.sql @@ -0,0 +1,6 @@ +SELECT + id, + platform_key as value, + platform_name as label +FROM embedding_platforms +ORDER BY platform_name; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-llm-connection.sql b/DSL/Resql/rag-search/POST/get-llm-connection.sql new file mode 100644 index 0000000..a1128df --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-llm-connection.sql @@ -0,0 +1,31 @@ +SELECT + id, + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + used_budget, + disconnect_on_budget_exceed, + environment, + connection_status, + created_at, + -- Azure credentials + deployment_name, + target_uri, + api_key, + -- AWS Bedrock credentials + secret_key, + access_key, + -- Embedding model credentials + embedding_access_key, + embedding_secret_key, + embedding_deployment_name, + embedding_target_uri, + embedding_azure_api_key +FROM llm_connections +WHERE id = :connection_id + AND connection_status <> 'deleted'; diff --git a/DSL/Resql/rag-search/POST/get-llm-connections-paginated.sql b/DSL/Resql/rag-search/POST/get-llm-connections-paginated.sql new file mode 100644 index 0000000..faf1600 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-llm-connections-paginated.sql @@ -0,0 +1,44 @@ +SELECT + id, + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + used_budget, + environment, + connection_status, + created_at, + CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS totalPages, + CASE + WHEN used_budget IS NULL OR used_budget = 0 OR (used_budget::DECIMAL / monthly_budget::DECIMAL) < (warn_budget_threshold::DECIMAL / 100.0) THEN 'within_budget' + WHEN stop_budget_threshold != 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (stop_budget_threshold::DECIMAL / 100.0) THEN 'over_budget' + WHEN stop_budget_threshold = 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= 1 THEN 'over_budget' + WHEN (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (warn_budget_threshold::DECIMAL / 100.0) THEN 'close_to_exceed' + ELSE 'within_budget' + END AS budget_status +FROM llm_connections +WHERE connection_status <> 'deleted' + AND environment = 'testing' + AND (:llm_platform IS NULL OR :llm_platform = '' OR llm_platform = :llm_platform) + AND (:llm_model IS NULL OR :llm_model = '' OR llm_model = :llm_model) + AND (:environment IS NULL OR :environment = '' OR environment = :environment) +ORDER BY + CASE WHEN :sorting = 'connection_name asc' THEN connection_name END ASC, + CASE WHEN :sorting = 'connection_name desc' THEN connection_name END DESC, + CASE WHEN :sorting = 'llm_platform asc' THEN llm_platform END ASC, + CASE WHEN :sorting = 'llm_platform desc' THEN llm_platform END DESC, + CASE WHEN :sorting = 'llm_model asc' THEN llm_model END ASC, + CASE WHEN :sorting = 'llm_model desc' THEN llm_model END DESC, + CASE WHEN :sorting = 'monthly_budget asc' THEN monthly_budget END ASC, + CASE WHEN :sorting = 'monthly_budget desc' THEN monthly_budget END DESC, + CASE WHEN :sorting = 'environment asc' THEN environment END ASC, + CASE WHEN :sorting = 'environment desc' THEN environment END DESC, + CASE WHEN :sorting = 'created_at asc' THEN created_at END ASC, + CASE WHEN :sorting = 'created_at desc' THEN created_at END DESC, + created_at DESC -- Default fallback sorting +OFFSET ((GREATEST(:page, 1) - 1) * :page_size) LIMIT :page_size; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-llm-models-by-platform.sql b/DSL/Resql/rag-search/POST/get-llm-models-by-platform.sql new file mode 100644 index 0000000..861a97d --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-llm-models-by-platform.sql @@ -0,0 +1,11 @@ +SELECT + lm.id, + lm.model_key as value, + lm.model_name as label, + lm.platform_id, + lp.platform_key, + lp.platform_name +FROM llm_models lm +JOIN llm_platforms lp ON lm.platform_id = lp.id +AND (:platform_key IS NULL OR lp.platform_key = :platform_key) +ORDER BY lm.model_name; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-llm-platforms.sql b/DSL/Resql/rag-search/POST/get-llm-platforms.sql new file mode 100644 index 0000000..2840f3c --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-llm-platforms.sql @@ -0,0 +1,6 @@ +SELECT + id, + platform_key as value, + platform_name as label +FROM llm_platforms +ORDER BY platform_name; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-production-connection-filtered.sql b/DSL/Resql/rag-search/POST/get-production-connection-filtered.sql new file mode 100644 index 0000000..4d5ced0 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-production-connection-filtered.sql @@ -0,0 +1,54 @@ +SELECT + id, + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + used_budget, + environment, + connection_status, + created_at, + deployment_name, + target_uri, + api_key, + secret_key, + access_key, + embedding_secret_key, + embedding_access_key, + embedding_deployment_name, + embedding_target_uri, + embedding_azure_api_key, + -- Calculate budget status based on usage percentage and configured thresholds + CASE + WHEN used_budget IS NULL OR used_budget = 0 OR (used_budget::DECIMAL / monthly_budget::DECIMAL) < (warn_budget_threshold::DECIMAL / 100.0) THEN 'within_budget' + WHEN stop_budget_threshold != 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (stop_budget_threshold::DECIMAL / 100.0) THEN 'over_budget' + WHEN stop_budget_threshold = 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= 1 THEN 'over_budget' + WHEN (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (warn_budget_threshold::DECIMAL / 100.0) THEN 'close_to_exceed' + ELSE 'within_budget' + END AS budget_status +FROM llm_connections +WHERE environment = 'production' + AND connection_status <> 'deleted' + AND (:llm_platform IS NULL OR :llm_platform = '' OR llm_platform = :llm_platform) + AND (:llm_model IS NULL OR :llm_model = '' OR llm_model = :llm_model) + AND (:embedding_platform IS NULL OR :embedding_platform = '' OR embedding_platform = :embedding_platform) + AND (:embedding_model IS NULL OR :embedding_model = '' OR embedding_model = :embedding_model) + AND (:connection_status IS NULL OR :connection_status = '' OR connection_status = :connection_status) +ORDER BY + CASE WHEN :sorting = 'connection_name asc' THEN connection_name END ASC, + CASE WHEN :sorting = 'connection_name desc' THEN connection_name END DESC, + CASE WHEN :sorting = 'llm_platform asc' THEN llm_platform END ASC, + CASE WHEN :sorting = 'llm_platform desc' THEN llm_platform END DESC, + CASE WHEN :sorting = 'llm_model asc' THEN llm_model END ASC, + CASE WHEN :sorting = 'llm_model desc' THEN llm_model END DESC, + CASE WHEN :sorting = 'monthly_budget asc' THEN monthly_budget END ASC, + CASE WHEN :sorting = 'monthly_budget desc' THEN monthly_budget END DESC, + CASE WHEN :sorting = 'created_at asc' THEN created_at END ASC, + CASE WHEN :sorting = 'created_at desc' THEN created_at END DESC, + created_at DESC -- Default fallback sorting +LIMIT 1; diff --git a/DSL/Resql/rag-search/POST/get-production-connection.sql b/DSL/Resql/rag-search/POST/get-production-connection.sql new file mode 100644 index 0000000..eca9f97 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-production-connection.sql @@ -0,0 +1,25 @@ +SELECT + id, + connection_name, + used_budget, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + environment, + connection_status, + created_at, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + CASE + WHEN used_budget IS NULL OR used_budget = 0 OR (used_budget::DECIMAL / monthly_budget::DECIMAL) < (warn_budget_threshold::DECIMAL / 100.0) THEN 'within_budget' + WHEN stop_budget_threshold != 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (stop_budget_threshold::DECIMAL / 100.0) THEN 'over_budget' + WHEN stop_budget_threshold = 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= 1 THEN 'over_budget' + WHEN (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (warn_budget_threshold::DECIMAL / 100.0) THEN 'close_to_exceed' + ELSE 'within_budget' + END AS budget_status +FROM llm_connections +WHERE environment = 'production' +ORDER BY created_at DESC +LIMIT 1; diff --git a/DSL/Resql/rag-search/POST/get-testing-connection.sql b/DSL/Resql/rag-search/POST/get-testing-connection.sql new file mode 100644 index 0000000..93e9149 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-testing-connection.sql @@ -0,0 +1,25 @@ +SELECT + id, + connection_name, + used_budget, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + environment, + connection_status, + created_at, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + CASE + WHEN used_budget IS NULL OR used_budget = 0 OR (used_budget::DECIMAL / monthly_budget::DECIMAL) < (warn_budget_threshold::DECIMAL / 100.0) THEN 'within_budget' + WHEN stop_budget_threshold != 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (stop_budget_threshold::DECIMAL / 100.0) THEN 'over_budget' + WHEN stop_budget_threshold = 0 AND (used_budget::DECIMAL / monthly_budget::DECIMAL) >= 1 THEN 'over_budget' + WHEN (used_budget::DECIMAL / monthly_budget::DECIMAL) >= (warn_budget_threshold::DECIMAL / 100.0) THEN 'close_to_exceed' + ELSE 'within_budget' + END AS budget_status +FROM llm_connections +WHERE environment = 'testing' +ORDER BY created_at DESC +LIMIT 1; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-user-role.sql b/DSL/Resql/rag-search/POST/get-user-role.sql new file mode 100644 index 0000000..39a51f4 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-user-role.sql @@ -0,0 +1,10 @@ +SELECT ua.authority_name AS authorities +FROM "user" u + INNER JOIN (SELECT authority_name, user_id + FROM user_authority AS ua + WHERE ua.id IN (SELECT max(id) + FROM user_authority + GROUP BY user_id)) ua ON u.id_code = ua.user_id +WHERE u.id_code = :userIdCode + AND status <> 'deleted' + AND id IN (SELECT max(id) FROM "user" WHERE id_code = :userIdCode) diff --git a/DSL/Resql/rag-search/POST/get-user-with-roles.sql b/DSL/Resql/rag-search/POST/get-user-with-roles.sql new file mode 100644 index 0000000..8ef5044 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-user-with-roles.sql @@ -0,0 +1,15 @@ +SELECT DISTINCT u.login, + u.first_name, + u.last_name, + u.id_code, + u.display_name, + u.csa_title, + u.csa_email, + ua.authority_name AS authorities +FROM "user" u + LEFT JOIN (SELECT authority_name, user_id + FROM user_authority AS ua + WHERE ua.id IN (SELECT max(id) + FROM user_authority + GROUP BY user_id)) ua ON u.id_code = ua.user_id +WHERE login = :login; diff --git a/DSL/Resql/rag-search/POST/get-user.sql b/DSL/Resql/rag-search/POST/get-user.sql new file mode 100644 index 0000000..18bef7f --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-user.sql @@ -0,0 +1,5 @@ +SELECT id_code +FROM "user" +WHERE id_code = :userIdCode + AND status <> 'deleted' + AND id IN (SELECT max(id) FROM "user" WHERE id_code = :userIdCode) \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/get-users-with-roles-by-role.sql b/DSL/Resql/rag-search/POST/get-users-with-roles-by-role.sql new file mode 100644 index 0000000..50ec519 --- /dev/null +++ b/DSL/Resql/rag-search/POST/get-users-with-roles-by-role.sql @@ -0,0 +1,41 @@ +SELECT u.login, + u.first_name, + u.last_name, + u.id_code AS userIdCode, + u.display_name, + u.csa_title, + u.csa_email, + ua.authority_name AS authorities, + CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS total_pages +FROM "user" u +LEFT JOIN ( + SELECT authority_name, user_id, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY id DESC) AS rn + FROM user_authority AS ua + WHERE authority_name && ARRAY [ :roles ]::character varying array + AND ua.id IN ( + SELECT max(id) + FROM user_authority + GROUP BY user_id + ) +) ua ON u.id_code = ua.user_id +WHERE u.status <> 'deleted' + AND array_length(authority_name, 1) > 0 + AND u.id IN ( + SELECT max(id) + FROM "user" + GROUP BY id_code + ) +ORDER BY + CASE WHEN :sorting = 'name asc' THEN u.first_name END ASC, + CASE WHEN :sorting = 'name desc' THEN u.first_name END DESC, + CASE WHEN :sorting = 'idCode asc' THEN u.id_code END ASC, + CASE WHEN :sorting = 'idCode desc' THEN u.id_code END DESC, + CASE WHEN :sorting = 'Role asc' THEN ua.authority_name END ASC, + CASE WHEN :sorting = 'Role desc' THEN ua.authority_name END DESC, + CASE WHEN :sorting = 'displayName asc' THEN u.display_name END ASC, + CASE WHEN :sorting = 'displayName desc' THEN u.display_name END DESC, + CASE WHEN :sorting = 'csaTitle asc' THEN u.csa_title END ASC, + CASE WHEN :sorting = 'csaTitle desc' THEN u.csa_title END DESC, + CASE WHEN :sorting = 'csaEmail asc' THEN u.csa_email END ASC, + CASE WHEN :sorting = 'csaEmail desc' THEN u.csa_email END DESC +OFFSET ((GREATEST(:page, 1) - 1) * :page_size) LIMIT :page_size; diff --git a/DSL/Resql/rag-search/POST/insert-llm-connection.sql b/DSL/Resql/rag-search/POST/insert-llm-connection.sql new file mode 100644 index 0000000..29465ce --- /dev/null +++ b/DSL/Resql/rag-search/POST/insert-llm-connection.sql @@ -0,0 +1,70 @@ +INSERT INTO llm_connections ( + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + environment, + connection_status, + created_at, + deployment_name, + target_uri, + api_key, + secret_key, + access_key, + embedding_access_key, + embedding_secret_key, + embedding_deployment_name, + embedding_target_uri, + embedding_azure_api_key +) VALUES ( + :connection_name, + :llm_platform, + :llm_model, + :embedding_platform, + :embedding_model, + :monthly_budget, + :warn_budget_threshold, + :stop_budget_threshold, + :disconnect_on_budget_exceed, + :environment, + :connection_status, + :created_at::timestamp with time zone, + :deployment_name, + :target_uri, + :api_key, + :secret_key, + :access_key, + :embedding_access_key, + :embedding_secret_key, + :embedding_deployment_name, + :embedding_target_uri, + :embedding_azure_api_key +) RETURNING + id, + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + environment, + connection_status, + created_at, + deployment_name, + target_uri, + api_key, + secret_key, + access_key, + embedding_secret_key, + embedding_access_key, + embedding_deployment_name, + embedding_target_uri, + embedding_azure_api_key diff --git a/DSL/Resql/rag-search/POST/insert-user-role.sql b/DSL/Resql/rag-search/POST/insert-user-role.sql new file mode 100644 index 0000000..e2bfe3b --- /dev/null +++ b/DSL/Resql/rag-search/POST/insert-user-role.sql @@ -0,0 +1,2 @@ +INSERT INTO user_authority (user_id, authority_name, created) +VALUES (:userIdCode, ARRAY [ :roles ], :created::timestamp with time zone); \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/insert-user.sql b/DSL/Resql/rag-search/POST/insert-user.sql new file mode 100644 index 0000000..0fd7c12 --- /dev/null +++ b/DSL/Resql/rag-search/POST/insert-user.sql @@ -0,0 +1,2 @@ +INSERT INTO "user" (login, first_name, last_name, display_name, password_hash, id_code, status, created, csa_title, csa_email) +VALUES (:userIdCode, :firstName, :lastName, :displayName, :displayName, :userIdCode, (:status)::user_status, :created::timestamp with time zone, :csaTitle, :csaEmail); diff --git a/DSL/Resql/rag-search/POST/mock-get-data-from-kb.sql b/DSL/Resql/rag-search/POST/mock-get-data-from-kb.sql new file mode 100644 index 0000000..9c9dc1b --- /dev/null +++ b/DSL/Resql/rag-search/POST/mock-get-data-from-kb.sql @@ -0,0 +1,5 @@ +SELECT + client_id, + client_data_hash, + signed_s3_url +FROM public.mock_ckb; diff --git a/DSL/Resql/rag-search/POST/reset-llm-connection-used-budget.sql b/DSL/Resql/rag-search/POST/reset-llm-connection-used-budget.sql new file mode 100644 index 0000000..581f0b9 --- /dev/null +++ b/DSL/Resql/rag-search/POST/reset-llm-connection-used-budget.sql @@ -0,0 +1,13 @@ +UPDATE llm_connections +SET + used_budget = 0.00 +WHERE connection_status <> 'deleted' +RETURNING + id, + connection_name, + monthly_budget, + used_budget, + (monthly_budget - used_budget) AS remaining_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed; diff --git a/DSL/Resql/rag-search/POST/store-inference-result.sql b/DSL/Resql/rag-search/POST/store-inference-result.sql new file mode 100644 index 0000000..089e92d --- /dev/null +++ b/DSL/Resql/rag-search/POST/store-inference-result.sql @@ -0,0 +1,34 @@ +INSERT INTO inference_results ( + chat_id, + user_question, + refined_questions, + conversation_history, + ranked_chunks, + embedding_scores, + final_answer, + environment, + llm_connection_id, + created_at +) VALUES ( + :chat_id, + :user_question, + :refined_questions::JSONB, + :conversation_history::JSONB, + :ranked_chunks::JSONB, + :embedding_scores::JSONB, + :final_answer, + :environment, + :llm_connection_id, + :created_at::timestamp with time zone +) RETURNING + id, + chat_id, + user_question, + refined_questions, + conversation_history, + ranked_chunks, + embedding_scores, + final_answer, + environment, + llm_connection_id, + created_at; diff --git a/DSL/Resql/rag-search/POST/store-testing-inference-result.sql b/DSL/Resql/rag-search/POST/store-testing-inference-result.sql new file mode 100644 index 0000000..faf9a2c --- /dev/null +++ b/DSL/Resql/rag-search/POST/store-testing-inference-result.sql @@ -0,0 +1,13 @@ +INSERT INTO inference_results ( + llm_connection_id, + user_question, + final_answer, + environment, + created_at +) VALUES ( + :llm_connection_id, + :user_question, + :final_answer, + :environment, + :created_at::timestamp with time zone +) RETURNING id, llm_connection_id, user_question, final_answer, environment, created_at; diff --git a/DSL/Resql/rag-search/POST/update-agency-hash.sql b/DSL/Resql/rag-search/POST/update-agency-hash.sql new file mode 100644 index 0000000..3882738 --- /dev/null +++ b/DSL/Resql/rag-search/POST/update-agency-hash.sql @@ -0,0 +1,11 @@ +UPDATE public.agency_sync +SET + agency_data_hash = :newAgencyDataHash, + data_url = :dataUrl, + updated_at = NOW() +WHERE agency_id = :agencyId +RETURNING + agency_id, + agency_data_hash, + data_url, + updated_at; diff --git a/DSL/Resql/rag-search/POST/update-llm-connection-environment.sql b/DSL/Resql/rag-search/POST/update-llm-connection-environment.sql new file mode 100644 index 0000000..5b894c9 --- /dev/null +++ b/DSL/Resql/rag-search/POST/update-llm-connection-environment.sql @@ -0,0 +1,23 @@ +UPDATE llm_connections +SET + environment = :environment +WHERE id = :connection_id +RETURNING + id, + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + environment, + connection_status, + created_at, + deployment_name, + target_uri, + api_key, + secret_key, + access_key; diff --git a/DSL/Resql/rag-search/POST/update-llm-connection-status.sql b/DSL/Resql/rag-search/POST/update-llm-connection-status.sql new file mode 100644 index 0000000..f71194a --- /dev/null +++ b/DSL/Resql/rag-search/POST/update-llm-connection-status.sql @@ -0,0 +1,22 @@ +UPDATE llm_connections +SET connection_status = :connection_status +WHERE id = :connection_id +RETURNING + id, + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + environment, + connection_status, + created_at, + deployment_name, + target_uri, + api_key, + secret_key, + access_key; diff --git a/DSL/Resql/rag-search/POST/update-llm-connection-used-budget.sql b/DSL/Resql/rag-search/POST/update-llm-connection-used-budget.sql new file mode 100644 index 0000000..ba6cd4d --- /dev/null +++ b/DSL/Resql/rag-search/POST/update-llm-connection-used-budget.sql @@ -0,0 +1,14 @@ +UPDATE llm_connections +SET + used_budget = used_budget + :usage +WHERE id = :connection_id +RETURNING + id, + connection_name, + monthly_budget, + used_budget, + (monthly_budget - used_budget) AS remaining_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + connection_status; \ No newline at end of file diff --git a/DSL/Resql/rag-search/POST/update-llm-connection.sql b/DSL/Resql/rag-search/POST/update-llm-connection.sql new file mode 100644 index 0000000..3fa7bc6 --- /dev/null +++ b/DSL/Resql/rag-search/POST/update-llm-connection.sql @@ -0,0 +1,51 @@ +UPDATE llm_connections +SET + connection_name = :connection_name, + llm_platform = :llm_platform, + llm_model = :llm_model, + embedding_platform = :embedding_platform, + embedding_model = :embedding_model, + monthly_budget = :monthly_budget, + warn_budget_threshold = :warn_budget_threshold, + stop_budget_threshold = :stop_budget_threshold, + disconnect_on_budget_exceed = :disconnect_on_budget_exceed, + environment = :environment, + -- Azure credentials + deployment_name = :deployment_name, + target_uri = :target_uri, + api_key = :api_key, + -- AWS Bedrock credentials + secret_key = :secret_key, + access_key = :access_key, + -- Embedding model credentials + -- Embedding platform specific credentials + embedding_access_key = :embedding_access_key, + embedding_secret_key = :embedding_secret_key, + embedding_deployment_name = :embedding_deployment_name, + embedding_target_uri = :embedding_target_uri, + embedding_azure_api_key = :embedding_azure_api_key +WHERE id = :connection_id +RETURNING + id, + connection_name, + llm_platform, + llm_model, + embedding_platform, + embedding_model, + monthly_budget, + warn_budget_threshold, + stop_budget_threshold, + disconnect_on_budget_exceed, + environment, + connection_status, + created_at, + deployment_name, + target_uri, + api_key, + secret_key, + access_key, + embedding_secret_key, + embedding_access_key, + embedding_deployment_name, + embedding_target_uri, + embedding_azure_api_key; diff --git a/DSL/Resql/rag-search/POST/update-user.sql b/DSL/Resql/rag-search/POST/update-user.sql new file mode 100644 index 0000000..688e8df --- /dev/null +++ b/DSL/Resql/rag-search/POST/update-user.sql @@ -0,0 +1,16 @@ +INSERT INTO "user" (id_code, login, password_hash, first_name, last_name, display_name, status, created, csa_title, csa_email) +SELECT + :userIdCode, + login, + password_hash, + :firstName, + :lastName, + :displayName, + :status::user_status, + :created::timestamp with time zone, + :csaTitle, + :csaEmail +FROM "user" +WHERE id = ( + SELECT MAX(id) FROM "user" WHERE id_code = :userIdCode +); diff --git a/DSL/Ruuter.private/rag-search/GET/.guard b/DSL/Ruuter.private/rag-search/GET/.guard new file mode 100644 index 0000000..ff4b523 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/.guard @@ -0,0 +1,33 @@ +check_for_cookie: + switch: + - condition: ${incoming.headers == null || incoming.headers.cookie == null} + next: guard_fail + next: authenticate + +authenticate: + template: "[#RAG_SEARCH_PROJECT_LAYER]/check-user-authority" + requestType: templates + headers: + cookie: ${incoming.headers.cookie} + result: authority_result + next: log_cookie + +log_cookie: + log: "Cookie received: ${incoming.headers.cookie}" + next: check_authority_result + +check_authority_result: + switch: + - condition: ${authority_result !== "false"} + next: guard_success + next: guard_fail + +guard_success: + return: "success" + status: 200 + next: end + +guard_fail: + return: "unauthorized" + status: 401 + next: end diff --git a/DSL/Ruuter.private/rag-search/GET/accounts/logout.yml b/DSL/Ruuter.private/rag-search/GET/accounts/logout.yml new file mode 100644 index 0000000..0d513ce --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/accounts/logout.yml @@ -0,0 +1,63 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'LOGOUT'" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + headers: + - field: cookie + type: string + description: "Cookie field" + +get_user_info: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-userinfo" + contentType: plaintext + headers: + cookie: ${incoming.headers.cookie} + plaintext: "customJwtCookie" + result: res + next: check_user_info_response + +check_user_info_response: + switch: + - condition: ${200 <= res.response.statusCodeValue && res.response.statusCodeValue < 300} + next: blacklistCustomJwt + next: return_bad_request + +blacklistCustomJwt: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-blacklist" + contentType: plaintext + headers: + cookie: ${incoming.headers.cookie} + plaintext: "customJwtCookie" + result: blacklist_res + next: assign_cookie + +assign_cookie: + assign: + setCookie: + customJwtCookie: null + Domain: "[#DOMAIN]" + Max-Age: 0 + Secure: true + HttpOnly: true + SameSite: "Lax" + next: return_result + +return_result: + headers: + Set-Cookie: ${setCookie} + return: "Logged Out Successfully" + next: end + +return_bad_request: + return: "error: bad request" + status: 400 + next: end diff --git a/DSL/Ruuter.private/rag-search/GET/accounts/user-role.yml b/DSL/Ruuter.private/rag-search/GET/accounts/user-role.yml new file mode 100644 index 0000000..a33c199 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/accounts/user-role.yml @@ -0,0 +1,53 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'USER-ROLE'" + method: get + accepts: json + returns: json + namespace: rag-search + allowlist: + headers: + - field: cookie + type: string + description: "Cookie field" + +get_user_info: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-userinfo" + contentType: plaintext + headers: + cookie: ${incoming.headers.cookie} + plaintext: + "customJwtCookie" + result: res + next: check_user_info_response + +check_user_info_response: + switch: + - condition: ${200 <= res.response.statusCodeValue && res.response.statusCodeValue < 300} + next: assignIdCode + next: returnNotFound + +assignIdCode: + assign: + idCode: ${res.response.body.idCode} + next: getUserRole + +getUserRole: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-user-role" + body: + userIdCode: ${idCode} + result: roles_res + next: returnSuccess + +returnSuccess: + return: ${roles_res.response.body?.[0]?.authorities ?? []} + next: end + +returnNotFound: + return: "error: not found" + next: end diff --git a/DSL/Ruuter.private/rag-search/GET/auth/jwt/extend.yml b/DSL/Ruuter.private/rag-search/GET/auth/jwt/extend.yml new file mode 100644 index 0000000..673f274 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/auth/jwt/extend.yml @@ -0,0 +1,41 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'EXTEND'" + method: get + accepts: json + returns: json + namespace: global-classifier + allowlist: + headers: + - field: cookie + type: string + description: "Cookie field" + +extend_cookie: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-extend" + contentType: plaintext + headers: + cookie: ${incoming.headers.cookie} + plaintext: + "customJwtCookie" + result: cookie_result + next: assign_cookie + +assign_cookie: + assign: + setCookie: + customJwtCookie: ${cookie_result.response.body.token} + Domain: "[#DOMAIN]" + Secure: true + HttpOnly: true + SameSite: "Lax" + next: return_value + +return_value: + headers: + Set-Cookie: ${setCookie} + return: ${cookie_result.response.body.token} + next: end diff --git a/DSL/Ruuter.private/rag-search/GET/auth/jwt/userinfo.yml b/DSL/Ruuter.private/rag-search/GET/auth/jwt/userinfo.yml new file mode 100644 index 0000000..012d0a4 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/auth/jwt/userinfo.yml @@ -0,0 +1,27 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'USERINFO'" + method: get + accepts: json + returns: json + namespace: global-classifier + allowlist: + headers: + - field: cookie + type: string + description: "Cookie field" + +get_user_info: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-userinfo" + contentType: plaintext + headers: + cookie: ${incoming.headers.cookie} + plaintext: + "customJwtCookie" + result: res + +return_result: + return: ${res.response.body} diff --git a/DSL/Ruuter.private/rag-search/GET/embedding/models.yml b/DSL/Ruuter.private/rag-search/GET/embedding/models.yml new file mode 100644 index 0000000..a71c31f --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/embedding/models.yml @@ -0,0 +1,27 @@ +declaration: + call: declare + version: 0.1 + description: "Get LLM models by platform" + method: get + accepts: query + returns: json + namespace: rag-search + allowlist: + params: + - field: embedding_platform_key + type: string + description: "Embedding Platform key to filter models" + +get_llm_models: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-embedding-models-by-platform" + body: + embedding_platform_key: ${incoming.params.embedding_platform_key} + result: models_result + next: return_success + +return_success: + return: ${models_result.response.body} + status: 200 + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/GET/embedding/platforms.yml b/DSL/Ruuter.private/rag-search/GET/embedding/platforms.yml new file mode 100644 index 0000000..6ca09c3 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/embedding/platforms.yml @@ -0,0 +1,19 @@ +declaration: + call: declare + version: 0.1 + description: "Get all active LLM platforms" + method: get + returns: json + namespace: rag-search + +get_llm_platforms: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-embedding-platforms" + result: embedding_platforms_result + next: return_success + +return_success: + return: ${embedding_platforms_result.response.body} + status: 200 + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/GET/llm-connections/cost/check.yml b/DSL/Ruuter.private/rag-search/GET/llm-connections/cost/check.yml new file mode 100644 index 0000000..df51bbb --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/llm-connections/cost/check.yml @@ -0,0 +1,57 @@ +declaration: + call: declare + version: 0.1 + description: "Check if production LLM connection's used budget has exceeded warn or stop budget thresholds" + method: get + accepts: json + returns: json + namespace: rag-search + +get_production_connection_budget_status: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-production-connection" + body: {} + result: budget_result + next: check_budget_status + +check_budget_status: + switch: + - condition: "${budget_result.response.body.length > 0}" + next: process_budget_status + next: return_no_production_connection + +process_budget_status: + assign: + used_budget: '${budget_result.response.body[0].usedBudget || 0}' + monthly_budget: '${budget_result.response.body[0].monthlyBudget}' + warn_threshold: '${budget_result.response.body[0].warnBudgetThreshold}' + stop_threshold: '${budget_result.response.body[0].stopBudgetThreshold}' + warn_budget_amount: '${(monthly_budget * warn_threshold) / 100}' + stop_budget_amount: '${(monthly_budget * stop_threshold) / 100}' + exceeded_stop_budget: '${stop_budget_amount != 0 && used_budget >= stop_budget_amount}' + exceeded_warn_budget: '${used_budget >= warn_budget_amount}' + within_budget: '${used_budget < warn_budget_amount}' + used_budget_percentage: '${(used_budget * 100) / monthly_budget}' + + next: process_warnings + +process_warnings: + assign: + response: { + data: '${budget_result.response.body[0]}', + used_budget_percentage: '${used_budget_percentage}', + exceeded_stop_budget: '${exceeded_stop_budget}', + exceeded_warn_budget: '${exceeded_warn_budget}', + } + next: return_budget_status + +return_budget_status: + return: ${response} + status: 200 + next: end + +return_no_production_connection: + return: "No production LLM connection found" + status: 404 + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/GET/llm-connections/list.yml b/DSL/Ruuter.private/rag-search/GET/llm-connections/list.yml new file mode 100644 index 0000000..62cf04e --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/llm-connections/list.yml @@ -0,0 +1,84 @@ +declaration: + call: declare + version: 0.1 + description: "Get paginated list of LLM connections" + method: get + accepts: json + returns: json + namespace: rag-search + allowlist: + params: + - field: pageNumber + type: number + description: "Page number (1-based)" + - field: pageSize + type: number + description: "Number of items per page" + - field: sortBy + type: string + description: "Field to sort by (e.g. 'llm_platform', 'created_at')" + - field: sortOrder + type: string + description: "Sort order: 'asc' or 'desc'" + - field: llmPlatform + type: string + description: "Filter by LLM platform" + - field: llmModel + type: string + description: "Filter by LLM model" + - field: environment + type: string + description: "Filter by deployment environment" + +extract_request_data: + assign: + pageNumber: ${Number(incoming.params.pageNumber) ?? 1} + pageSize: ${Number(incoming.params.pageSize) ?? 10} + sortBy: ${incoming.params.sortBy ?? "created_at"} + sortOrder: ${incoming.params.sortOrder ?? "desc"} + sorting: ${sortBy + " " + sortOrder} + llmPlatform: ${incoming.params.llmPlatform ?? ""} + llmModel: ${incoming.params.llmModel ?? ""} + environment: ${incoming.params.environment ?? ""} + next: validate_page_params + +validate_page_params: + switch: + - condition: ${pageNumber < 1} + next: return_invalid_page + - condition: ${pageSize < 1 || pageSize > 100} + next: return_invalid_page_size + next: get_llm_connections + +get_llm_connections: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connections-paginated" + body: + page: ${pageNumber} + page_size: ${pageSize} + sorting: ${sorting} + llm_platform: ${llmPlatform} + llm_model: ${llmModel} + environment: ${environment} + result: connections_result + next: transform_response + +transform_response: + assign: + response_data: ${connections_result.response.body} + next: return_success + +return_success: + return: ${response_data} + next: end + +return_invalid_page: + status: 400 + return: "Page number must be greater than 0" + next: end + +return_invalid_page_size: + status: 400 + return: "Page size must be between 1 and 100" + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/GET/llm-connections/production.yml b/DSL/Ruuter.private/rag-search/GET/llm-connections/production.yml new file mode 100644 index 0000000..b64e046 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/llm-connections/production.yml @@ -0,0 +1,61 @@ +declaration: + call: declare + version: 0.1 + description: "Get production LLM connection with optional filters" + method: get + returns: json + namespace: rag-search + allowlist: + params: + - field: llmPlatform + type: string + description: "Filter by LLM platform" + - field: llmModel + type: string + description: "Filter by LLM model" + - field: embeddingPlatform + type: string + description: "Filter by embedding platform" + - field: embeddingModel + type: string + description: "Filter by embedding model" + - field: connectionStatus + type: string + description: "Filter by connection status" + - field: sortBy + type: string + description: "Field to sort by" + - field: sortOrder + type: string + description: "Sort order: 'asc' or 'desc'" + +extract_request_data: + assign: + llmPlatform: ${incoming.params.llmPlatform ?? ""} + llmModel: ${incoming.params.llmModel ?? ""} + embeddingPlatform: ${incoming.params.embeddingPlatform ?? ""} + embeddingModel: ${incoming.params.embeddingModel ?? ""} + connectionStatus: ${incoming.params.connectionStatus ?? ""} + sortBy: ${incoming.params.sortBy ?? "created_at"} + sortOrder: ${incoming.params.sortOrder ?? "desc"} + sorting: ${sortBy + " " + sortOrder} + next: get_production_connection + +get_production_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-production-connection-filtered" + body: + llm_platform: ${llmPlatform} + llm_model: ${llmModel} + embedding_platform: ${embeddingPlatform} + embedding_model: ${embeddingModel} + connection_status: ${connectionStatus} + sorting: ${sorting} + result: connection_result + next: return_success + +return_success: + return: ${connection_result.response.body} + status: 200 + next: end diff --git a/DSL/Ruuter.private/rag-search/GET/llm/models.yml b/DSL/Ruuter.private/rag-search/GET/llm/models.yml new file mode 100644 index 0000000..abf54e9 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/llm/models.yml @@ -0,0 +1,27 @@ +declaration: + call: declare + version: 0.1 + description: "Get LLM models by platform" + method: get + accepts: query + returns: json + namespace: rag-search + allowlist: + params: + - field: platform_key + type: string + description: "Platform key to filter models" + +get_llm_models: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-models-by-platform" + body: + platform_key: ${incoming.params.platform_key} + result: models_result + next: return_success + +return_success: + return: ${models_result.response.body} + status: 200 + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/GET/llm/platforms.yml b/DSL/Ruuter.private/rag-search/GET/llm/platforms.yml new file mode 100644 index 0000000..e3d29df --- /dev/null +++ b/DSL/Ruuter.private/rag-search/GET/llm/platforms.yml @@ -0,0 +1,19 @@ +declaration: + call: declare + version: 0.1 + description: "Get all active LLM platforms" + method: get + returns: json + namespace: rag-search + +get_llm_platforms: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-platforms" + result: platforms_result + next: return_success + +return_success: + return: ${platforms_result.response.body} + status: 200 + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/POST/.guard b/DSL/Ruuter.private/rag-search/POST/.guard new file mode 100644 index 0000000..967acc3 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/.guard @@ -0,0 +1,28 @@ +check_for_cookie: + switch: + - condition: ${incoming.headers == null || incoming.headers.cookie == null} + next: guard_fail + next: authenticate + +authenticate: + template: "[#RAG_SEARCH_PROJECT_LAYER]/check-user-authority" + requestType: templates + headers: + cookie: ${incoming.headers.cookie} + result: authority_result + +check_authority_result: + switch: + - condition: ${authority_result !== "false"} + next: guard_success + next: guard_fail + +guard_success: + return: "success" + status: 200 + next: end + +guard_fail: + return: "unauthorized" + status: 401 + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/accounts/.guard b/DSL/Ruuter.private/rag-search/POST/accounts/.guard new file mode 100644 index 0000000..733e24e --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/accounts/.guard @@ -0,0 +1,28 @@ +check_for_cookie: + switch: + - condition: ${incoming.headers == null || incoming.headers.cookie == null} + next: guard_fail + next: authenticate + +authenticate: + template: "[#RAG_SEARCH_PROJECT_LAYER]/check-user-authority-admin" + requestType: templates + headers: + cookie: ${incoming.headers.cookie} + result: authority_result + +check_authority_result: + switch: + - condition: ${authority_result !== "false"} + next: guard_success + next: guard_fail + +guard_success: + return: "success" + status: 200 + next: end + +guard_fail: + return: "unauthorized" + status: 401 + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/accounts/add.yml b/DSL/Ruuter.private/rag-search/POST/accounts/add.yml new file mode 100644 index 0000000..f347a39 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/accounts/add.yml @@ -0,0 +1,89 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'ADD'" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: csaTitle + type: string + description: "Body field 'csaTitle'" + - field: csa_email + type: string + description: "Body field 'csa_email'" + - field: firstName + type: string + description: "Body field 'firstName'" + - field: lastName + type: string + description: "Body field 'lastName'" + - field: roles + type: array + description: "Body field 'roles'" + - field: userIdCode + type: string + description: "Body field 'userIdCode'" + +extractRequestData: + assign: + firstName: ${incoming.body.firstName} + lastName: ${incoming.body.lastName} + userIdCode: ${incoming.body.userIdCode} + displayName: ${incoming.body.firstName} + csaTitle: ${incoming.body.csaTitle} + csa_email: ${incoming.body.csa_email} + roles: ${incoming.body.roles} + +getUser: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-user" + body: + userIdCode: ${userIdCode} + result: res + next: checkIfUserExists + +checkIfUserExists: + switch: + - condition: "${res.response.body.length > 0}" + next: return_exists + next: addUser + +addUser: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/insert-user" + body: + created: ${new Date().toISOString()} + status: "active" + firstName: ${firstName} + lastName: ${lastName} + userIdCode: ${userIdCode} + displayName: ${displayName} + csaTitle: ${csaTitle} + csaEmail: ${csa_email} + result: add_user_res + next: addRoles + +addRoles: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/insert-user-role" + body: + userIdCode: ${userIdCode} + roles: ${roles} + created: ${new Date().toISOString()} + result: add_roles_res + next: return_result + +return_result: + return: "User added successfully" + next: end + +return_exists: + return: "error: user already exists" + status: 400 + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/accounts/delete.yml b/DSL/Ruuter.private/rag-search/POST/accounts/delete.yml new file mode 100644 index 0000000..b6634dc --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/accounts/delete.yml @@ -0,0 +1,29 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'DELETE'" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: userIdCode + type: string + description: "Body field 'userIdCode'" + +extractRequestData: + assign: + userId: ${incoming.body.userIdCode} + +setConfigurationValue: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/delete-user" + body: + userIdCode: ${userId} + created: ${new Date().toISOString()} + result: res + +return_result: + return: ${res.response.body} diff --git a/DSL/Ruuter.private/rag-search/POST/accounts/edit.yml b/DSL/Ruuter.private/rag-search/POST/accounts/edit.yml new file mode 100644 index 0000000..5bd8986 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/accounts/edit.yml @@ -0,0 +1,94 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'EDIT'" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: csaTitle + type: string + description: "Body field 'csaTitle'" + - field: csa_email + type: string + description: "Body field 'csa_email'" + - field: displayName + type: string + description: "Body field 'displayName'" + - field: firstName + type: string + description: "Body field 'firstName'" + - field: lastName + type: string + description: "Body field 'lastName'" + - field: roles + type: array + description: "Body field 'roles'" + - field: userIdCode + type: string + description: "Body field 'userIdCode'" + +extractRequestData: + assign: + firstName: ${incoming.body.firstName} + lastName: ${incoming.body.lastName} + userIdCode: ${incoming.body.userIdCode} + displayName: ${incoming.body.displayName} + csaTitle: ${incoming.body.csaTitle} + csa_email: ${incoming.body.csa_email} + roles: ${incoming.body.roles} + +getUser: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-user" + body: + userIdCode: ${userIdCode} + result: res + next: checkIfUserExists + +checkIfUserExists: + switch: + - condition: "${res.response.body.length > 0}" + next: updateUser + next: return_not_exists + +updateUser: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/update-user" + body: + created: ${new Date().toISOString()} + status: "active" + firstName: ${firstName} + lastName: ${lastName} + userIdCode: ${userIdCode} + displayName: ${displayName} + csaTitle: ${csaTitle} + csaEmail: ${csa_email} + result: add_user_res + next: updateRoles + +updateRoles: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/insert-user-role" + body: + userIdCode: ${userIdCode} + roles: ${roles} + created: ${new Date().toISOString()} + result: add_roles_res + next: return_result + +return_result: + return: "User updated successfully" + status: 200 + next: end + +return_not_exists: + return: "error: user does not exist" + status: 400 + next: end + diff --git a/DSL/Ruuter.private/rag-search/POST/accounts/exists.yml b/DSL/Ruuter.private/rag-search/POST/accounts/exists.yml new file mode 100644 index 0000000..5f0a7fb --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/accounts/exists.yml @@ -0,0 +1,40 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'EXISTS'" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: userIdCode + type: string + description: "Body field 'userIdCode'" + +extractRequestData: + assign: + userId: ${incoming.body.userIdCode} + +getUser: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-user" + body: + userIdCode: ${userId} + result: res + next: checkIfUserExists + +checkIfUserExists: + switch: + - condition: "${res.response.body.length > 0}" + next: return_exists + next: return_not_exists + +return_exists: + return: "true" + next: end + +return_not_exists: + return: "false" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/accounts/users.yml b/DSL/Ruuter.private/rag-search/POST/accounts/users.yml new file mode 100644 index 0000000..41cb56f --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/accounts/users.yml @@ -0,0 +1,39 @@ +declaration: + call: declare + version: 0.1 + description: "Description placeholder for 'USERS'" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: page + type: number + description: "Body field 'page'" + - field: page_size + type: number + description: "Body field 'page_size'" + - field: sorting + type: string + description: "Body field 'sorting'" + +getUsers: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-users-with-roles-by-role" + body: + page: ${incoming.body.page} + page_size: ${incoming.body.page_size} + sorting: ${incoming.body.sorting} + roles: + [ + "ROLE_ADMINISTRATOR", + "ROLE_MODEL_TRAINER" + ] + result: res + next: return_result + +return_result: + return: ${res.response.body} + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/ckb/agency_data_import.yml b/DSL/Ruuter.private/rag-search/POST/ckb/agency_data_import.yml new file mode 100644 index 0000000..ba892e5 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/ckb/agency_data_import.yml @@ -0,0 +1,33 @@ +declaration: + call: declare + version: 0.1 + description: "Get agency data information by agency IDs" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: agencyIds + type: array + description: "Array of unique institution IDs" + +extractRequestData: + assign: + agencyIds: ${incoming.body.agencyIds || []} + log: "Received request for agency data: ${agencyIds}" + +get_agency_data: + call: http.post + args: + url: "[#GLOBAL_CLASSIFIER_RESQL]/mock-get-data-from-kb" + headers: + type: json + body: + agencyIds: ${agencyIds} + result: agency_data_info + next: return_result + +return_result: + return: ${agency_data_info.response.body} + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/POST/inference/production.yml b/DSL/Ruuter.private/rag-search/POST/inference/production.yml new file mode 100644 index 0000000..39fbf7e --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/inference/production.yml @@ -0,0 +1,121 @@ +declaration: + call: declare + version: 0.1 + description: "Call LLM orchestration service with budget validation" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: chatId + type: string + description: "Chat ID" + - field: message + type: string + description: "User message" + - field: authorId + type: string + description: "Author ID" + - field: conversationHistory + type: array + description: "Conversation history" + - field: url + type: string + description: "URL reference" + +extract_request_data: + assign: + chatId: ${incoming.body.chatId} + message: ${incoming.body.message} + authorId: ${incoming.body.authorId} + conversationHistory: ${incoming.body.conversationHistory} + url: ${incoming.body.url} + next: get_production_connection + +get_production_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-production-connection" + body: {} + result: production_connection_result + next: validate_production_connection + +validate_production_connection: + switch: + - condition: "${production_connection_result.response.body.length > 0}" + next: extract_connection_id + next: return_no_production_connection + +extract_connection_id: + assign: + connection_id: ${Number(production_connection_result.response.body[0].id)} + next: check_budget_status + +check_budget_status: + call: http.post + args: + url: "[#RAG_SEARCH_RUUTER_PRIVATE]/llm-connections/usage/check" + body: + connection_id: ${connection_id} + headers: + cookie: ${incoming.headers.cookie} + result: budget_check_result + next: validate_budget_status + +validate_budget_status: + switch: + - condition: ${budget_check_result.response.body.response.isLLMConnectionDisconnected} + next: assign_disconnected_response + - condition: "${budget_check_result.response.statusCodeValue >= 400}" + next: return_budget_check_error + next: call_orchestrate_endpoint + +call_orchestrate_endpoint: + call: http.post + args: + url: "[#RAG_SEARCH_LLM_ORCHESTRATOR]" + body: + chatId: ${chatId} + message: ${message} + authorId: ${authorId} + conversationHistory: ${conversationHistory} + url: ${url} + environment: "production" + headers: + Content-Type: "application/json" + result: orchestrate_result + next: assign_response + +assign_response: + assign: + response: "${orchestrate_result.response.body}" + next: return_orchestrate_response + +return_orchestrate_response: + return: ${response} + next: end + +assign_disconnected_response: + assign: + disconnected_response: + { + chatId: "${chatId}", + content: "The LLM connection is currently unavailable. Your request couldn't be processed. Please retry shortly.", + status: 400 + } + next: return_connection_disconnected + +return_connection_disconnected: + status: 400 + return: ${disconnected_response} + next: end + +return_budget_check_error: + return: ${budget_check_result.response.body} + next: end + +return_no_production_connection: + status: 404 + return: "No production connection found" + next: end \ No newline at end of file diff --git a/DSL/Ruuter.private/rag-search/POST/inference/results/view.yml b/DSL/Ruuter.private/rag-search/POST/inference/results/view.yml new file mode 100644 index 0000000..5d619b4 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/inference/results/view.yml @@ -0,0 +1,47 @@ +declaration: + call: declare + version: 0.1 + description: "View/get inference result" + method: post + accepts: json + returns: json + namespace: inference-results + allowlist: + body: + - field: llmConnectionId + type: number + description: "LLM connection ID" + - field: message + type: string + description: "User message/question" + +extract_request_data: + assign: + llmConnectionId: ${incoming.body.llmConnectionId} + message: ${incoming.body.message} + next: validate_request + +validate_request: + switch: + - condition: ${llmConnectionId != null && message != null} + next: generate_mock_response + next: return_bad_request + +generate_mock_response: + assign: + data: { + chatId: 10, + llmServiceActive: true, + questionOutOfLlmScope: true, + content: "Random answer with citations\n - https://gov.ee/sample1,\n - https://gov.ee/sample1" + } + next: return_success + +return_success: + return: ${data} + next: end + +return_bad_request: + status: 400 + return: "llmConnectionId and message are required" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/inference/test.yml b/DSL/Ruuter.private/rag-search/POST/inference/test.yml new file mode 100644 index 0000000..4acd463 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/inference/test.yml @@ -0,0 +1,102 @@ +declaration: + call: declare + version: 0.1 + description: "Call LLM orchestration service with budget validation" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connectionId + type: string + description: "Connection ID" + - field: message + type: string + description: "User message" + +extract_request_data: + assign: + connectionId: ${incoming.body.connectionId} + message: ${incoming.body.message} + next: get_connection + +get_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connectionId} + result: connection_result + next: validate_connection + +validate_connection: + switch: + - condition: "${connection_result.response.body.length > 0}" + next: check_budget_status + next: return_no_test_connection + +check_budget_status: + call: http.post + args: + url: "[#RAG_SEARCH_RUUTER_PRIVATE]/llm-connections/usage/check" + body: + connection_id: ${connectionId} + headers: + cookie: ${incoming.headers.cookie} + result: budget_check_result + next: validate_budget_status + +validate_budget_status: + switch: + - condition: ${budget_check_result.response.body.response.isLLMConnectionDisconnected} + next: assign_disconnected_response + - condition: "${budget_check_result.response.statusCodeValue >= 400}" + next: return_budget_check_error + next: call_orchestrate_endpoint + +call_orchestrate_endpoint: + call: http.post + args: + url: "[#RAG_SEARCH_LLM_ORCHESTRATOR]/test" + body: + connectionId: ${connectionId} + message: ${message} + environment: "testing" + headers: + Content-Type: "application/json" + result: orchestrate_result + next: assign_response + +assign_response: + assign: + response: "${orchestrate_result.response.body}" + next: return_orchestrate_response + +return_orchestrate_response: + return: ${response} + next: end + +assign_disconnected_response: + assign: + disconnected_response: + { + connectionId: "${connectionId}", + content: "The LLM connection is currently unavailable. Your request couldn’t be processed. Please retry shortly.", + status: 400 + } + next: return_connection_disconnected + +return_connection_disconnected: + status: 400 + return: ${disconnected_response} + next: end + +return_budget_check_error: + return: ${budget_check_result.response.body} + next: end + +return_no_test_connection: + status: 404 + return: "No test connection found" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/add.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/add.yml new file mode 100644 index 0000000..5e7326a --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/add.yml @@ -0,0 +1,191 @@ +declaration: + call: declare + version: 0.1 + description: "Add a new LLM connection" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_name + type: string + description: "Connection name for identification" + - field: llm_platform + type: string + description: "LLM platform (e.g., Azure AI, OpenAI)" + - field: llm_model + type: string + description: "LLM model (e.g., GPT-4o)" + - field: embedding_platform + type: string + description: "Embedding platform (e.g., Azure AI, OpenAI)" + - field: embedding_model + type: string + description: "Embedding model (e.g., Ada-200-1)" + - field: monthly_budget + type: number + description: "Monthly budget amount" + - field: warn_budget_threshold + type: number + description: "Warn budget threshold percentage" + - field: stop_budget_threshold + type: number + description: "Stop budget threshold percentage" + - field: disconnect_on_budget_exceed + type: boolean + description: "Automatically disconnect when budget threshold is exceeded" + - field: deployment_environment + type: string + description: "Deployment environment (Testing or Production)" + # Azure credentials + - field: deployment_name + type: string + description: "Azure deployment name" + - field: target_uri + type: string + description: "Custom endpoint URI" + - field: api_key + type: string + description: "API key" + # AWS Bedrock credentials + - field: secret_key + type: string + description: "AWS secret key" + - field: access_key + type: string + description: "AWS access key" + # Embedding model credentials + # Embedding AWS Bedrock credentials + - field: embedding_access_key + type: string + description: "AWS access key for embedding model" + - field: embedding_secret_key + type: string + description: "AWS secret key for embedding model" + # Embedding Azure credentials + - field: embedding_deployment_name + type: string + description: "Azure embedding deployment name" + - field: embedding_target_uri + type: string + description: "Azure embedding endpoint URI" + - field: embedding_azure_api_key + type: string + description: "Azure embedding API key" + +extract_request_data: + assign: + connection_name: ${incoming.body.connection_name} + llm_platform: ${incoming.body.llm_platform} + llm_model: ${incoming.body.llm_model} + embedding_platform: ${incoming.body.embedding_platform} + embedding_model: ${incoming.body.embedding_model} + monthly_budget: ${incoming.body.monthly_budget} + warn_budget_threshold: ${incoming.body.warn_budget_threshold || 0} + stop_budget_threshold: ${incoming.body.stop_budget_threshold || 0} + disconnect_on_budget_exceed: ${incoming.body.disconnect_on_budget_exceed || false} + deployment_environment: ${incoming.body.deployment_environment} + deployment_name: ${incoming.body.deployment_name || ""} + target_uri: ${incoming.body.target_uri || ""} + api_key: ${incoming.body.api_key || ""} + secret_key: ${incoming.body.secret_key || ""} + access_key: ${incoming.body.access_key || ""} + # Embedding platform specific credentials + embedding_access_key: ${incoming.body.embedding_access_key || ""} + embedding_secret_key: ${incoming.body.embedding_secret_key || ""} + embedding_deployment_name: ${incoming.body.embedding_deployment_name || ""} + embedding_target_uri: ${incoming.body.embedding_target_uri || ""} + embedding_azure_api_key: ${incoming.body.embedding_azure_api_key || ""} + created_at: ${new Date().toISOString()} + next: validate_environment + +validate_environment: + switch: + - condition: ${deployment_environment == "testing" || deployment_environment == "production"} + next: check_production_environment + next: return_invalid_environment + +check_production_environment: + switch: + - condition: ${deployment_environment == "production"} + next: get_existing_production_connection + next: add_llm_connection + +get_existing_production_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-production-connection" + result: existing_production_result + next: update_existing_production_to_testing + +update_existing_production_to_testing: + switch: + - condition: ${existing_production_result.response.body && existing_production_result.response.body.length > 0} + next: update_production_connection + next: add_llm_connection + +update_production_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/update-llm-connection-environment" + body: + connection_id: ${existing_production_result.response.body[0].id} + environment: "testing" + result: update_result + next: add_llm_connection + +add_llm_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/insert-llm-connection" + body: + connection_name: ${connection_name} + llm_platform: ${llm_platform} + llm_model: ${llm_model} + embedding_platform: ${embedding_platform} + embedding_model: ${embedding_model} + monthly_budget: ${monthly_budget} + warn_budget_threshold: ${warn_budget_threshold} + stop_budget_threshold: ${stop_budget_threshold} + disconnect_on_budget_exceed: ${disconnect_on_budget_exceed} + environment: ${deployment_environment} + connection_status: "active" + created_at: ${new Date().toISOString()} + deployment_name: ${deployment_name} + target_uri: ${target_uri} + api_key: ${api_key} + secret_key: ${secret_key} + access_key: ${access_key} + # Embedding platform specific credentials + embedding_access_key: ${embedding_access_key} + embedding_secret_key: ${embedding_secret_key} + embedding_deployment_name: ${embedding_deployment_name} + embedding_target_uri: ${embedding_target_uri} + embedding_azure_api_key: ${embedding_azure_api_key} + result: connection_result + next: assign_connection_response + +assign_connection_response: + assign: + response: { + id: "${connection_result.response.body[0].id}", + status: 201, + operationSuccess: true + } + next: return_success + +return_success: + return: ${response} + status: 200 + next: end + +return_invalid_environment: + status: 400 + return: "error: environment must be 'Testing' or 'Production'" + next: end + +return_unauthorized: + status: 401 + return: "error: unauthorized" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/cost/update.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/cost/update.yml new file mode 100644 index 0000000..d0e55c3 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/cost/update.yml @@ -0,0 +1,150 @@ +declaration: + call: declare + version: 0.1 + description: "Update used budget for an LLM connection" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_id + type: number + description: "LLM connection ID" + - field: usage + type: number + description: "Usage amount to add to current used_budget" + +extract_request_data: + assign: + connection_id: ${Number(incoming.body.connection_id)} + usage: ${Number(incoming.body.usage)} + next: validate_request + +validate_request: + switch: + - condition: ${connection_id && usage >= 0} + next: check_connection_exists + next: return_bad_request + +check_connection_exists: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connection_id} + result: existing_connection + next: validate_connection_exists + +validate_connection_exists: + switch: + - condition: "${existing_connection.response.body.length > 0}" + next: update_used_budget + next: return_not_found + +update_used_budget: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/update-llm-connection-used-budget" + body: + connection_id: ${connection_id} + usage: ${usage} + result: update_result + next: check_update_status + +check_update_status: + switch: + - condition: ${200 <= update_result.response.statusCodeValue && update_result.response.statusCodeValue < 300} + next: check_budget_threshold + next: return_update_failed + +check_budget_threshold: + assign: + updated_connection: ${update_result.response.body[0]} + disconnect_flag: ${updated_connection.disconnectOnBudgetExceed} + monthly_budget: ${Number(updated_connection.monthlyBudget)} + used_budget: ${Number(updated_connection.usedBudget)} + stop_threshold: ${Number(updated_connection.stopBudgetThreshold)} + threshold_amount: ${(monthly_budget / 100) * stop_threshold} + should_deactivate: ${disconnect_flag && used_budget >= threshold_amount} + next: evaluate_deactivation + +evaluate_deactivation: + switch: + - condition: ${should_deactivate} + next: deactivate_connection + next: format_success_response + +deactivate_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/deactivate-llm-connection-budget-exceed" + body: + connection_id: ${connection_id} + result: deactivate_result + next: check_deactivate_status + +check_deactivate_status: + switch: + - condition: ${200 <= deactivate_result.response.statusCodeValue && deactivate_result.response.statusCodeValue < 300} + next: assignDisconnectResponse + next: format_success_response + +assignDisconnectResponse: + assign: + data_budget_exceeded: { + data: '${deactivate_result.response.body[0]}', + } + next: format_budget_exceeded_response + +format_budget_exceeded_response: + assign: + response_budget_exceeded: { + data: '${data_budget_exceeded.data}', + message: 'Used budget updated successfully. Connection deactivated due to budget threshold exceeded.', + budgetExceeded: true, + operationSuccess: true, + statusCode: 200 + } + next: return_budget_exceeded + +format_success_response: + assign: + response_success: { + data: '${update_result.response.body[0]}', + budgetExceeded: false, + message: 'Used budget updated successfully', + operationSuccess: true, + statusCode: 200 + } + next: return_success + +return_budget_exceeded: + return: ${response_budget_exceeded} + status: 200 + next: end + +return_success: + return: ${response_success} + status: 200 + next: end + +return_not_found: + status: 404 + return: "error: connection not found" + next: end + +return_bad_request: + status: 400 + return: "error: connection_id and usage (>= 0) are required" + next: end + +return_update_failed: + status: 500 + return: "error: failed to update used budget" + next: end + +return_unauthorized: + status: 401 + return: "error: unauthorized" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/delete.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/delete.yml new file mode 100644 index 0000000..bbe5dd8 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/delete.yml @@ -0,0 +1,56 @@ +declaration: + call: declare + version: 0.1 + description: "Delete an LLM connection (soft delete)" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_id + type: number + description: "LLM connection ID" + +extract_request_data: + assign: + connection_id: ${incoming.body.connection_id} + next: check_connection_exists + +check_connection_exists: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connection_id} + result: existing_connection + next: validate_connection_exists + +validate_connection_exists: + switch: + - condition: "${existing_connection.response.body.length > 0}" + next: delete_llm_connection + next: return_not_found + +delete_llm_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/delete-llm-connection" + body: + connection_id: ${Number(connection_id)} + result: delete_result + next: return_success + +return_success: + return: "LLM connection deleted successfully" + next: end + +return_not_found: + status: 404 + return: "error: connection not found" + next: end + +return_unauthorized: + status: 401 + return: "error: unauthorized" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/edit.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/edit.yml new file mode 100644 index 0000000..84b375d --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/edit.yml @@ -0,0 +1,172 @@ +declaration: + call: declare + version: 0.1 + description: "Update an existing LLM connection" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_id + type: number + description: "LLM connection ID" + - field: connection_name + type: string + description: "Connection name for identification" + - field: llm_platform + type: string + description: "LLM platform (e.g., Azure AI, OpenAI)" + - field: llm_model + type: string + description: "LLM model (e.g., GPT-4o)" + - field: embedding_platform + type: string + description: "Embedding platform (e.g., Azure AI, OpenAI)" + - field: embedding_model + type: string + description: "Embedding model (e.g., Ada-200-1)" + - field: monthly_budget + type: number + description: "Monthly budget amount" + - field: warn_budget_threshold + type: number + description: "Warn budget threshold percentage" + - field: stop_budget_threshold + type: number + description: "Stop budget threshold percentage" + - field: disconnect_on_budget_exceed + type: boolean + description: "Automatically disconnect when budget threshold is exceeded" + - field: deployment_environment + type: string + description: "Deployment environment (Testing or Production)" + - field: deployment_name + type: string + description: "Azure deployment name" + - field: target_uri + type: string + description: "Custom endpoint URI" + - field: api_key + type: string + description: "API key" + - field: secret_key + type: string + description: "AWS secret key" + - field: access_key + type: string + description: "AWS access key" + # Embedding AWS Bedrock credentials + - field: embedding_access_key + type: string + description: "AWS access key for embedding model" + - field: embedding_secret_key + type: string + description: "AWS secret key for embedding model" + # Embedding Azure credentials + - field: embedding_deployment_name + type: string + description: "Azure embedding deployment name" + - field: embedding_target_uri + type: string + description: "Azure embedding endpoint URI" + - field: embedding_azure_api_key + type: string + description: "Azure embedding API key" + +extract_request_data: + assign: + connection_id: ${Number(incoming.body.connection_id)} + connection_name: ${incoming.body.connection_name} + llm_platform: ${incoming.body.llm_platform} + llm_model: ${incoming.body.llm_model} + embedding_platform: ${incoming.body.embedding_platform} + embedding_model: ${incoming.body.embedding_model} + monthly_budget: ${Number(incoming.body.monthly_budget)} + warn_budget_threshold: ${Number(incoming.body.warn_budget_threshold)} + stop_budget_threshold: ${Number(incoming.body.stop_budget_threshold)} + disconnect_on_budget_exceed: ${incoming.body.disconnect_on_budget_exceed} + environment: ${incoming.body.deployment_environment} + deployment_name: ${incoming.body.deployment_name || ""} + target_uri: ${incoming.body.target_uri || ""} + api_key: ${incoming.body.api_key || ""} + secret_key: ${incoming.body.secret_key || ""} + access_key: ${incoming.body.access_key || ""} + # Embedding platform specific credentials + embedding_access_key: ${incoming.body.embedding_access_key || ""} + embedding_secret_key: ${incoming.body.embedding_secret_key || ""} + embedding_deployment_name: ${incoming.body.embedding_deployment_name || ""} + embedding_target_uri: ${incoming.body.embedding_target_uri || ""} + embedding_azure_api_key: ${incoming.body.embedding_azure_api_key || ""} + updated_at: ${new Date().toISOString()} + next: validate_environment + +validate_environment: + switch: + - condition: ${environment == "testing" || environment == "production"} + next: check_connection_exists + next: return_invalid_environment + +check_connection_exists: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connection_id} + result: existing_connection + next: validate_connection_exists + +validate_connection_exists: + switch: + - condition: "${existing_connection.response.body.length > 0}" + next: update_llm_connection + next: return_not_found + +update_llm_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/update-llm-connection" + body: + connection_id: ${connection_id} + connection_name: ${connection_name} + llm_platform: ${llm_platform} + llm_model: ${llm_model} + embedding_platform: ${embedding_platform} + embedding_model: ${embedding_model} + monthly_budget: ${monthly_budget} + warn_budget_threshold: ${warn_budget_threshold} + stop_budget_threshold: ${stop_budget_threshold} + disconnect_on_budget_exceed: ${disconnect_on_budget_exceed} + environment: ${environment} + deployment_name: ${deployment_name} + target_uri: ${target_uri} + api_key: ${api_key} + secret_key: ${secret_key} + access_key: ${access_key} + # Embedding platform specific credentials + embedding_access_key: ${embedding_access_key} + embedding_secret_key: ${embedding_secret_key} + embedding_deployment_name: ${embedding_deployment_name} + embedding_target_uri: ${embedding_target_uri} + embedding_azure_api_key: ${embedding_azure_api_key} + result: connection_result + next: return_success + +return_success: + return: ${connection_result.response.body[0]} + next: end + +return_not_found: + status: 404 + return: "error: connection not found" + next: end + +return_invalid_environment: + status: 400 + return: "error: environment must be 'Testing' or 'Production'" + next: end + +return_unauthorized: + status: 401 + return: "error: unauthorized" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/exists.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/exists.yml new file mode 100644 index 0000000..f4fa321 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/exists.yml @@ -0,0 +1,46 @@ +declaration: + call: declare + version: 0.1 + description: "Check if an LLM connection exists" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_id + type: number + description: "LLM connection ID" + +extract_request_data: + assign: + connection_id: ${incoming.body.connection_id} + next: get_llm_connection + +get_llm_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connection_id} + result: connection_result + next: check_connection_exists + +check_connection_exists: + switch: + - condition: "${connection_result.response.body.length > 0}" + next: return_exists + next: return_not_exists + +return_exists: + return: "true" + next: end + +return_not_exists: + return: "false" + next: end + +return_unauthorized: + status: 401 + return: "error: unauthorized" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/get.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/get.yml new file mode 100644 index 0000000..7be38dd --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/get.yml @@ -0,0 +1,47 @@ +declaration: + call: declare + version: 0.1 + description: "Get a single LLM connection by ID" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_id + type: number + description: "LLM connection ID" + +extract_request_data: + assign: + connection_id: ${Number(incoming.body.connection_id)} + next: get_llm_connection + +get_llm_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connection_id} + result: connection_result + next: check_connection_exists + +check_connection_exists: + switch: + - condition: "${connection_result.response.body.length > 0}" + next: return_success + next: return_not_found + +return_success: + return: ${connection_result.response.body[0]} + next: end + +return_not_found: + status: 404 + return: "error: connection not found" + next: end + +return_unauthorized: + status: 401 + return: "error: unauthorized" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/update-status.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/update-status.yml new file mode 100644 index 0000000..953e392 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/update-status.yml @@ -0,0 +1,91 @@ +declaration: + call: declare + version: 0.1 + description: "Update LLM connection status (active/inactive)" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_id + type: number + description: "LLM connection ID" + - field: connection_status + type: string + description: "Connection status (active/inactive)" + +extract_request_data: + assign: + connection_id: ${Number(incoming.body.connection_id)} + connection_status: ${incoming.body.connection_status} + next: validate_request + +validate_request: + switch: + - condition: ${!connection_id || !connection_status} + next: return_bad_request + - condition: ${connection_status !== "active" && connection_status !== "inactive"} + next: return_invalid_status + next: check_connection_exists + +check_connection_exists: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connection_id} + result: existing_connection + next: validate_connection_exists + +validate_connection_exists: + switch: + - condition: "${existing_connection.response.body.length > 0}" + next: update_connection_status + next: return_not_found + +update_connection_status: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/update-llm-connection-status" + body: + connection_id: ${connection_id} + connection_status: ${connection_status} + result: update_result + next: check_update_status + +check_update_status: + switch: + - condition: ${200 <= update_result.response.statusCodeValue && update_result.response.statusCodeValue < 300} + next: return_success + next: return_update_failed + +return_success: + return: ${update_result.response.body[0]} + status: 200 + next: end + +return_not_found: + status: 404 + return: "error: connection not found" + next: end + +return_bad_request: + status: 400 + return: "error: connection_id and connection_status are required" + next: end + +return_invalid_status: + status: 400 + return: "error: connection_status must be 'active' or 'inactive'" + next: end + +return_update_failed: + status: 500 + return: "error: failed to update connection status" + next: end + +return_unauthorized: + status: 401 + return: "error: unauthorized" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/llm-connections/usage/check.yml b/DSL/Ruuter.private/rag-search/POST/llm-connections/usage/check.yml new file mode 100644 index 0000000..eabf745 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/llm-connections/usage/check.yml @@ -0,0 +1,99 @@ +declaration: + call: declare + version: 0.1 + description: "Check budget usage and either proceed with orchestration or return budget exceeded response" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: connection_id + type: number + description: "LLM connection ID" + +extract_request_data: + assign: + connection_id: ${Number(incoming.body.connection_id)} + next: get_connection + +get_connection: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connection_id} + result: connection_result + next: check_connection_exists + +check_connection_exists: + switch: + - condition: "${connection_result.response.body.length > 0}" + next: calculate_budget_threshold + next: return_connection_not_found + +calculate_budget_threshold: + assign: + connection_data: ${connection_result.response.body[0]} + monthly_budget: ${Number(connection_data.monthlyBudget)} + used_budget: ${Number(connection_data.usedBudget)} + stop_budget_threshold: ${Number(connection_data.stopBudgetThreshold)} + disconnect_on_budget_exceed: ${connection_data.disconnectOnBudgetExceed} + budget_threshold_amount: ${monthly_budget / 100 * stop_budget_threshold} + next: check_budget_threshold + +check_budget_threshold: + switch: + - condition: ${used_budget >= budget_threshold_amount} + next: handle_budget_exceeded + next: format_budget_within_threshold + +handle_budget_exceeded: + switch: + - condition: ${disconnect_on_budget_exceed} + next: format_budget_exceeded_disconnected + next: format_budget_exceeded_not_disconnected + +format_budget_within_threshold: + assign: + response_budget_within_threshold: + { + isBudgetExceed: false, + isLLMConnectionDisconnected: false, + } + next: return_budget_within_threshold + +format_budget_exceeded_not_disconnected: + assign: + response_budget_exceeded_not_disconnected: + { + isBudgetExceed: true, + isLLMConnectionDisconnected: false, + } + next: return_budget_exceeded_not_disconnected + +format_budget_exceeded_disconnected: + assign: + response_budget_exceeded_disconnected: + { + isBudgetExceed: true, + isLLMConnectionDisconnected: true, + } + next: return_budget_exceeded_disconnected + +return_budget_within_threshold: + return: ${response_budget_within_threshold} + next: end + +return_budget_exceeded_not_disconnected: + return: ${response_budget_exceeded_not_disconnected} + next: end + +return_budget_exceeded_disconnected: + return: ${response_budget_exceeded_disconnected} + next: end + +return_connection_not_found: + status: 404 + return: "Connection not found" + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/vault/secret/create.yml b/DSL/Ruuter.private/rag-search/POST/vault/secret/create.yml new file mode 100644 index 0000000..3fa2f46 --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/vault/secret/create.yml @@ -0,0 +1,161 @@ +declaration: + call: declare + version: 0.1 + description: "Insert model metadata" + method: post + accepts: json + returns: json + namespace: classifier + allowlist: + body: + - field: connectionId + type: string + description: "Body field 'connectionId'" + - field: llmPlatform + type: string + description: "Body field 'llmPlatform'" + - field: llmModel + type: array + description: "Body field 'llmModel'" + - field: secretKey + type: string + description: "Body field 'secretKey'" + - field: accessKey + type: string + description: "Body field 'accessKey'" + - field: deploymentName + type: string + description: "Body field 'deploymentName'" + - field: targetUrl + type: string + description: "Body field 'targetUrl'" + - field: apiKey + type: string + description: "Body field 'apiKey'" + - field: embeddingModel + type: string + description: "Body field 'embeddingModel'" + - field: embeddingPlatform + type: string + description: "Body field 'embeddingPlatform'" + # Embedding AWS Bedrock credentials + - field: embeddingAccessKey + type: string + description: "Body field 'embeddingAccessKey'" + - field: embeddingSecretKey + type: string + description: "Body field 'embeddingSecretKey'" + # Embedding Azure credentials + - field: embeddingDeploymentName + type: string + description: "Body field 'embeddingDeploymentName'" + - field: embeddingTargetUri + type: string + description: "Body field 'embeddingTargetUri'" + - field: embeddingAzureApiKey + type: string + description: "Body field 'embeddingAzureApiKey'" + - field: deploymentEnvironment + type: string + description: "Body field 'deploymentEnvironment'" + headers: + - field: cookie + type: string + description: "Cookie field" + +extract_request_data: + assign: + connectionId: ${incoming.body.connectionId} + llmPlatform: ${incoming.body.llmPlatform} + llmModel: ${incoming.body.llmModel} + secretKey: ${incoming.body.secretKey} + accessKey: ${incoming.body.accessKey} + deploymentName: ${incoming.body.deploymentName} + targetUrl: ${incoming.body.targetUrl} + apiKey: ${incoming.body.apiKey} + embeddingModel: ${incoming.body.embeddingModel} + embeddingPlatform: ${incoming.body.embeddingPlatform} + # Embedding AWS Bedrock credentials + embeddingAccessKey: ${incoming.body.embeddingAccessKey} + embeddingSecretKey: ${incoming.body.embeddingSecretKey} + # Embedding Azure credentials + embeddingDeploymentName: ${incoming.body.embeddingDeploymentName} + embeddingTargetUri: ${incoming.body.embeddingTargetUri} + embeddingAzureApiKey: ${incoming.body.embeddingAzureApiKey} + deploymentEnvironment: ${incoming.body.deploymentEnvironment} + cookie: ${incoming.headers.cookie} + next: check_provider + +check_provider: + switch: + - condition: ${llmPlatform == "aws"} + next: execute_aws_request + - condition: ${llmPlatform == "azure"} + next: execute_azure_request + next: assign_fail_response + +execute_aws_request: + call: http.post + args: + url: "[#RAG_SEARCH_CRON_MANAGER]/execute/store_in_vault/store_secrets" + query: + cookie: ${incoming.headers.cookie.replace('customJwtCookie=','')} #Removing the customJwtCookie phrase from payload to to send cookie token only + connectionId: ${connectionId} + llmPlatform: ${llmPlatform} + llmModel: ${llmModel} + secretKey: ${secretKey} + accessKey: ${accessKey} + embeddingModel: ${embeddingModel} + embeddingPlatform: ${embeddingPlatform} + # Embedding AWS Bedrock credentials + embeddingAccessKey: ${embeddingAccessKey} + embeddingSecretKey: ${embeddingSecretKey} + deploymentEnvironment: ${deploymentEnvironment} + result: cron_aws_res + next: return_aws_ok + +execute_azure_request: + call: http.post + args: + url: "[#RAG_SEARCH_CRON_MANAGER]/execute/store_in_vault/store_secrets" + query: + cookie: ${incoming.headers.cookie.replace('customJwtCookie=','')} #Removing the customJwtCookie phrase from payload to to send cookie token only + connectionId: ${connectionId} + llmPlatform: ${llmPlatform} + llmModel: ${llmModel} + deploymentName: ${deploymentName} + targetUrl: ${targetUrl} + apiKey: ${apiKey} + embeddingModel: ${embeddingModel} + embeddingPlatform: ${embeddingPlatform} + # Embedding Azure credentials + embeddingDeploymentName: ${embeddingDeploymentName} + embeddingTargetUri: ${embeddingTargetUri} + embeddingAzureApiKey: ${embeddingAzureApiKey} + deploymentEnvironment: ${deploymentEnvironment} + result: cron_azure_res + next: return_azure_ok + +assign_fail_response: + assign: + format_bad_res: { + message: 'Platform not supported', + operationSuccessful: false, + statusCode: 400 + } + next: return_bad_request + +return_aws_ok: + status: 200 + return: "Executed cron manager successfully to store aws secrets" + next: end + +return_azure_ok: + status: 200 + return: "Executed cron manager successfully to store azure secrets" + next: end + +return_bad_request: + status: 400 + return: ${format_bad_res} + next: end diff --git a/DSL/Ruuter.private/rag-search/POST/vault/secret/delete.yml b/DSL/Ruuter.private/rag-search/POST/vault/secret/delete.yml new file mode 100644 index 0000000..7cf146f --- /dev/null +++ b/DSL/Ruuter.private/rag-search/POST/vault/secret/delete.yml @@ -0,0 +1,120 @@ +declaration: + call: declare + version: 0.1 + description: "Delete vault secrets for LLM connection" + method: post + accepts: json + returns: json + namespace: classifier + allowlist: + body: + - field: connectionId + type: string + description: "Body field 'connectionId'" + - field: llmPlatform + type: string + description: "Body field 'llmPlatform'" + - field: llmModel + type: string + description: "Body field 'llmModel'" + - field: embeddingModel + type: string + description: "Body field 'embeddingModel'" + - field: embeddingPlatform + type: string + description: "Body field 'embeddingPlatform'" + - field: deploymentEnvironment + type: string + description: "Body field 'deploymentEnvironment'" + headers: + - field: cookie + type: string + description: "Cookie field" + +extract_request_data: + assign: + connectionId: ${incoming.body.connectionId} + llmPlatform: ${incoming.body.llmPlatform} + llmModel: ${incoming.body.llmModel} + embeddingModel: ${incoming.body.embeddingModel} + embeddingPlatform: ${incoming.body.embeddingPlatform} + deploymentEnvironment: ${incoming.body.deploymentEnvironment} + cookie: ${incoming.headers.cookie} + next: check_connection_exists + +check_connection_exists: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-llm-connection" + body: + connection_id: ${connectionId} + result: connection_result + next: validate_connection_response + +validate_connection_response: + switch: + - condition: ${connection_result.response.body && connection_result.response.body.length > 0} + next: execute_delete_request + next: assign_connection_not_found_error + +execute_delete_request: + call: http.post + args: + url: "[#RAG_SEARCH_CRON_MANAGER]/execute/delete_from_vault/delete_secrets" + query: + cookie: ${incoming.headers.cookie.replace('customJwtCookie=','')} #Removing the customJwtCookie phrase from payload to to send cookie token only + connectionId: ${connectionId} + llmPlatform: ${llmPlatform} + llmModel: ${llmModel} + embeddingModel: ${embeddingModel} + embeddingPlatform: ${embeddingPlatform} + deploymentEnvironment: ${deploymentEnvironment} + result: cron_delete_res + next: return_delete_ok + +assign_validation_error: + assign: + validation_error_res: { + message: 'Required fields missing: connectionId, llmPlatform, llmModel, and deploymentEnvironment are required', + operationSuccessful: false, + statusCode: 400 + } + next: return_validation_error + +assign_connection_not_found_error: + assign: + connection_not_found_res: { + message: 'Connection not found with the provided connectionId', + operationSuccessful: false, + statusCode: 404 + } + next: return_connection_not_found + +assign_fail_response: + assign: + format_bad_res: { + message: 'Platform not supported. Supported platforms: aws, azure', + operationSuccessful: false, + statusCode: 400 + } + next: return_bad_request + +return_delete_ok: + status: 200 + return: "Executed cron manager successfully to delete secrets from vault" + next: end + +return_validation_error: + status: 400 + return: ${validation_error_res} + next: end + +return_connection_not_found: + status: 404 + return: ${connection_not_found_res} + next: end + +return_bad_request: + status: 400 + return: ${format_bad_res} + next: end diff --git a/DSL/Ruuter.private/rag-search/TEMPLATES/check-user-authority-admin.yml b/DSL/Ruuter.private/rag-search/TEMPLATES/check-user-authority-admin.yml new file mode 100644 index 0000000..0e00e1e --- /dev/null +++ b/DSL/Ruuter.private/rag-search/TEMPLATES/check-user-authority-admin.yml @@ -0,0 +1,52 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'CHECK-USER-AUTHORITY'" + method: post + accepts: json + returns: json + namespace: global-classifier + allowlist: + headers: + - field: cookie + type: string + description: "Cookie field" + +get_cookie_info: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-userinfo" + contentType: plaintext + headers: + cookie: ${incoming.headers.cookie} + plaintext: "customJwtCookie" + result: res + next: check_cookie_info_response + +check_cookie_info_response: + switch: + - condition: ${200 <= res.response.statusCodeValue && res.response.statusCodeValue < 300} + next: check_user_authority + next: return_bad_request + +check_user_authority: + switch: + - condition: ${res.response.body === null} + next: return_unauthorized + - condition: ${res.response.body.authorities.includes("ROLE_ADMINISTRATOR")} + next: return_authorized + next: return_unauthorized + +return_authorized: + return: ${res.response.body} + next: end + +return_unauthorized: + status: 401 + return: false + next: end + +return_bad_request: + status: 400 + return: false + next: end diff --git a/DSL/Ruuter.private/rag-search/TEMPLATES/check-user-authority.yml b/DSL/Ruuter.private/rag-search/TEMPLATES/check-user-authority.yml new file mode 100644 index 0000000..59fd51c --- /dev/null +++ b/DSL/Ruuter.private/rag-search/TEMPLATES/check-user-authority.yml @@ -0,0 +1,52 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'CHECK-USER-AUTHORITY'" + method: post + accepts: json + returns: json + namespace: global-classifier + allowlist: + headers: + - field: cookie + type: string + description: "Cookie field" + +get_cookie_info: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-userinfo" + contentType: plaintext + headers: + cookie: ${incoming.headers.cookie} + plaintext: "customJwtCookie" + result: res + next: check_cookie_info_response + +check_cookie_info_response: + switch: + - condition: ${200 <= res.response.statusCodeValue && res.response.statusCodeValue < 300} + next: check_user_authority + next: return_bad_request + +check_user_authority: + switch: + - condition: ${res.response.body === null} + next: return_unauthorized + - condition: ${res.response.body.authorities.includes("ROLE_ADMINISTRATOR") || res.response.body.authorities.includes("ROLE_MODEL_TRAINER")} + next: return_authorized + next: return_unauthorized + +return_authorized: + return: ${res.response.body} + next: end + +return_unauthorized: + status: 401 + return: false + next: end + +return_bad_request: + status: 400 + return: false + next: end diff --git a/DSL/Ruuter.public/rag-search/POST/auth/login.yml b/DSL/Ruuter.public/rag-search/POST/auth/login.yml new file mode 100644 index 0000000..b093289 --- /dev/null +++ b/DSL/Ruuter.public/rag-search/POST/auth/login.yml @@ -0,0 +1,79 @@ +declaration: + call: declare + version: 0.1 + description: "Decription placeholder for 'LOGIN'" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: login + type: string + description: "Body field 'login'" + - field: password + type: string + description: "Body field 'password'" + +extractRequestData: + assign: + login: ${incoming.body.login} + password: ${incoming.body.password} + next: getUserWithRole + +getUserWithRole: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-user-with-roles" + body: + login: ${login} + password: ${password} + result: user_result + next: check_user_result + +check_user_result: + switch: + - condition: "${user_result.response.body.length > 0}" + next: get_session_length + next: return_user_not_found + +get_session_length: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-configuration" + body: + key: "session_length" + result: session_result + next: generate_cookie + +generate_cookie: + call: http.post + args: + url: "[#RAG_SEARCH_TIM]/jwt/custom-jwt-generate" + body: + JWTName: "customJwtCookie" + expirationInMinutes: ${session_result.response.body[0]?.value ?? '120'} + content: ${user_result.response.body[0]} + result: cookie_result + next: assign_cookie + +assign_cookie: + assign: + setCookie: + customJwtCookie: ${cookie_result.response.body.token} + Domain: "[#DOMAIN]" + Secure: true + HttpOnly: true + SameSite: "Lax" + next: return_value + +return_value: + headers: + Set-Cookie: ${setCookie} + return: ${cookie_result.response.body.token} + next: end + +return_user_not_found: + status: 400 + return: "User Not Found" + next: end diff --git a/DSL/Ruuter.public/rag-search/POST/ckb/agency-data-import.yml b/DSL/Ruuter.public/rag-search/POST/ckb/agency-data-import.yml new file mode 100644 index 0000000..9905b27 --- /dev/null +++ b/DSL/Ruuter.public/rag-search/POST/ckb/agency-data-import.yml @@ -0,0 +1,33 @@ +declaration: + call: declare + version: 0.1 + description: "Get agency data information by agency IDs" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: agencyIds + type: array + description: "Array of unique institution IDs" + +extractRequestData: + assign: + agencyIds: ${incoming.body.agencyIds || []} + log: "Received request for agency data: ${agencyIds}" + +get_agency_data: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/mock-get-data-from-kb" + headers: + type: json + body: + agencyIds: ${agencyIds} + result: agency_data_info + next: return_result + +return_result: + return: ${agency_data_info.response.body} + next: end \ No newline at end of file diff --git a/DSL/Ruuter.public/rag-search/POST/data/update.yml b/DSL/Ruuter.public/rag-search/POST/data/update.yml new file mode 100644 index 0000000..a3f21ea --- /dev/null +++ b/DSL/Ruuter.public/rag-search/POST/data/update.yml @@ -0,0 +1,135 @@ +declaration: + call: declare + version: 0.1 + description: "Resync new data from KB" + method: post + accepts: json + returns: json + namespace: rag-search + +get_agency_id: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/get-agency-id" + result: get_agency_id_result + next: log_result + +log_result: + log: ${get_agency_id_result.response.body[0].agencyId} + next: extract_params + +extract_params: + assign: + single_agency_id: ${get_agency_id_result.response.body[0].agencyId} + agency_ids: + - ${single_agency_id} + current_data_hash: ${get_agency_id_result.response.body[0].agencyDataHash} + next: logs_params + +logs_params: + log: "Agency ID: ${agency_ids}, Current Data Hash: ${current_data_hash}" + next: import_agency_data + +import_agency_data: + call: http.post + args: + url: "[#RAG_SEARCH_RUUTER_PUBLIC]/ckb/agency-data-import" + body: + agencyIds: ${agency_ids} + result: importResult + next: log_import_agency_data_response + +log_import_agency_data_response: + log: ${JSON.stringify(importResult.response)} + next: assign_import_agency_data + +assign_import_agency_data: + assign: + ckb_data_hash: ${importResult.response.body.response[0].clientDataHash} + signed_s3_url: ${importResult.response.body.response[0].signedS3Url} + next: check_has_match + +check_has_match: + switch: + - condition: ${current_data_hash === importResult.response.body.response[0].clientDataHash} + next: noAgencyData + - condition: true + next: sync_current_hash_with_ckb_latest_hash + +sync_current_hash_with_ckb_latest_hash: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/update-agency-hash" + body: + agencyId: ${single_agency_id} + newAgencyDataHash: ${ckb_data_hash} + dataUrl: ${signed_s3_url} + result: sync_agency_hash_result + next: log_sync_hash_result + on_error: handle_hash_update_error + +log_sync_hash_result: + log: "Current hash sync result: ${JSON.stringify(sync_agency_hash_result.response)}" + next: execute_cron_manager + +handle_hash_update_error: + log: "ERROR: Failed to update data hash - ${sync_agency_hash_result.error || 'Unknown error'}" + next: assign_hash_error_response + +assign_hash_error_response: + assign: + format_res: { + message: "Failed to update data hash. Data synchronization aborted.", + operationSuccessful: false, + error: "HASH_UPDATE_FAILED" + } + next: return_bad_request + +execute_cron_manager: + call: http.post + args: + url: "[#RAG_SEARCH_CRON_MANAGER]/execute/initiate_vector_indexer/vector_indexer" + query: + signedUrl: ${signed_s3_url} + clientDataHash: ${ckb_data_hash} + result: res + next: assign_success_response + +assign_success_response: + assign: + format_res: { + message: "Data synchronization initiated successfully", + operationSuccessful: true, + } + next: return_ok + +assign_fail_response: + assign: + format_res: { + message: "Data synchronization failed", + operationSuccessful: false, + } + next: return_bad_request + +return_ok: + status: 200 + return: ${format_res} + next: end + +return_bad_request: + status: 400 + return: ${format_res} + next: end + +noAgencyData: + assign: + response_data: + success: true + message: "No sync required - data is up to date" + next: return_no_sync_needed + +return_no_sync_needed: + status: 200 + return: ${response_data} + next: end + \ No newline at end of file diff --git a/DSL/Ruuter.public/rag-search/POST/inference/results/store.yml b/DSL/Ruuter.public/rag-search/POST/inference/results/store.yml new file mode 100644 index 0000000..19d8adf --- /dev/null +++ b/DSL/Ruuter.public/rag-search/POST/inference/results/store.yml @@ -0,0 +1,109 @@ +declaration: + call: declare + version: 0.1 + description: "Store production inference result with comprehensive data" + method: post + accepts: json + returns: json + namespace: rag-search + allowlist: + body: + - field: chat_id + type: string + description: "Chat ID" + - field: user_question + type: string + description: "User's raw question/input" + - field: refined_questions + type: object + description: "List of refined questions (LLM-generated)" + - field: conversation_history + type: object + description: "Prior messages array of {role, content}" + - field: ranked_chunks + type: object + description: "Retrieved chunks ranked with metadata" + - field: embedding_scores + type: object + description: "Distance scores for each chunk" + - field: final_answer + type: string + description: "LLM's final generated answer" + - field: environment + type: string + description: "Environment identifier (e.g., production, testing)" + - field: llm_connection_id + type: string + description: "Connection identifier" + +extract_request_data: + assign: + chat_id: ${incoming.body.chat_id} + user_question: ${incoming.body.user_question} + refined_questions: ${JSON.stringify(incoming.body.refined_questions) || null} + conversation_history: ${JSON.stringify(incoming.body.conversation_history) || null} + ranked_chunks: ${JSON.stringify(incoming.body.ranked_chunks) || null} + embedding_scores: ${JSON.stringify(incoming.body.embedding_scores) || null} + final_answer: ${incoming.body.final_answer} + environment: ${incoming.body.environment} + llm_connection_id: ${incoming.body.llm_connection_id} + created_at: ${new Date().toISOString()} + next: validate_required_fields + +validate_required_fields: + switch: + - condition: "${!user_question || !final_answer}" + next: return_bad_request + next: store_production_inference_result + +store_production_inference_result: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/store-inference-result" + body: + chat_id: ${chat_id} + user_question: ${user_question} + refined_questions: ${refined_questions} + conversation_history: ${conversation_history} + ranked_chunks: ${ranked_chunks} + embedding_scores: ${embedding_scores} + final_answer: ${final_answer} + environment: ${environment} + llm_connection_id: ${llm_connection_id} + created_at: ${created_at} + result: store_result + next: check_status + +check_status: + switch: + - condition: ${200 <= store_result.response.statusCodeValue && store_result.response.statusCodeValue < 300} + next: format_success_response + next: format_failed_response + +format_success_response: + assign: + data_success: { + data: '${store_result.response.body[0]}', + operationSuccess: true, + statusCode: 200 + } + next: return_success + +format_failed_response: + assign: + data_failed: { + data: '[]', + operationSuccess: false, + statusCode: 400 + } + next: return_bad_request + +return_success: + return: ${data_success} + status: 200 + next: end + +return_bad_request: + return: ${data_failed} + status: 400 + next: end \ No newline at end of file diff --git a/DSL/Ruuter.public/rag-search/POST/llm-connections/cost/reset.yml b/DSL/Ruuter.public/rag-search/POST/llm-connections/cost/reset.yml new file mode 100644 index 0000000..cc55fec --- /dev/null +++ b/DSL/Ruuter.public/rag-search/POST/llm-connections/cost/reset.yml @@ -0,0 +1,42 @@ +declaration: + call: declare + version: 0.1 + description: "Reset used budget for all LLM connections to 0" + method: post + accepts: json + returns: json + namespace: rag-search + +reset_used_budget: + call: http.post + args: + url: "[#RAG_SEARCH_RESQL]/reset-llm-connection-used-budget" + body: {} + result: reset_result + next: check_reset_status + +check_reset_status: + switch: + - condition: ${200 <= reset_result.response.statusCodeValue && reset_result.response.statusCodeValue < 300} + next: format_success_response + next: return_reset_failed + +format_success_response: + assign: + response_success: { + message: 'Used budget reset to 0 successfully for all connections', + totalConnections: '${reset_result.response.body.length}', + operationSuccess: true, + statusCode: 200 + } + next: return_success + +return_success: + return: ${response_success} + status: 200 + next: end + +return_reset_failed: + return: "error: failed to reset used budget" + status: 500 + next: end diff --git a/Dockerfile.llm_orchestration_service b/Dockerfile.llm_orchestration_service new file mode 100644 index 0000000..0a4f979 --- /dev/null +++ b/Dockerfile.llm_orchestration_service @@ -0,0 +1,24 @@ +FROM python:3.12-slim + +RUN apt-get update && apt-get install -y \ + curl \ + build-essential \ + g++ \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + +COPY . /app + +WORKDIR /app + +# Set Python path to include src directory +ENV PYTHONPATH="/app/src:$PYTHONPATH" + +RUN uv sync --locked + +EXPOSE 8100 + +# Run the FastAPI app via uvicorn +CMD ["uv","run","uvicorn", "src.llm_orchestration_service_api:app", "--host", "0.0.0.0", "--port", "8100"] \ No newline at end of file diff --git a/GUI/.dockerignore b/GUI/.dockerignore new file mode 100644 index 0000000..ab4f96a --- /dev/null +++ b/GUI/.dockerignore @@ -0,0 +1,7 @@ +node_modules +npm-debug.log +build +.git +*.md +.gitignore +.env.development diff --git a/GUI/.env.development b/GUI/.env.development new file mode 100644 index 0000000..39f5e47 --- /dev/null +++ b/GUI/.env.development @@ -0,0 +1,7 @@ +REACT_APP_RUUTER_API_URL=http://localhost:8086 +REACT_APP_RUUTER_PRIVATE_API_URL=http://localhost:8088 +REACT_APP_CUSTOMER_SERVICE_LOGIN=http://localhost:3004/et/dev-auth +REACT_APP_SERVICE_ID=conversations,settings,monitoring +REACT_APP_NOTIFICATION_NODE_URL=http://localhost:3005 +REACT_APP_CSP=upgrade-insecure-requests; default-src 'self'; font-src 'self' data:; img-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; object-src 'none'; connect-src 'self' http://localhost:8086 http://localhost:8088 http://localhost:3004 http://localhost:3005 ws://localhost; +REACT_APP_ENABLE_HIDDEN_FEATURES=TRUE \ No newline at end of file diff --git a/GUI/.eslintrc.json b/GUI/.eslintrc.json new file mode 100644 index 0000000..5e603ec --- /dev/null +++ b/GUI/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "react-app" +} diff --git a/GUI/.gitignore b/GUI/.gitignore new file mode 100644 index 0000000..d79b5ca --- /dev/null +++ b/GUI/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# testing +/coverage + +# production +/build + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/GUI/.prettierignore b/GUI/.prettierignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/GUI/.prettierignore @@ -0,0 +1 @@ +node_modules diff --git a/GUI/.prettierrc b/GUI/.prettierrc new file mode 100644 index 0000000..0a72520 --- /dev/null +++ b/GUI/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true +} diff --git a/GUI/Dockerfile.dev b/GUI/Dockerfile.dev new file mode 100644 index 0000000..48b7890 --- /dev/null +++ b/GUI/Dockerfile.dev @@ -0,0 +1,14 @@ +FROM node:22.0.0-alpine AS image +WORKDIR /app +COPY ./package.json . + +FROM image AS build +RUN npm install --legacy-peer-deps --mode=development +COPY . . +RUN ./node_modules/.bin/vite build --mode=development + +EXPOSE 3001 + +ENV REACT_APP_ENABLE_HIDDEN_FEATURES TRUE + +CMD ["npm", "run", "dev"] diff --git a/GUI/README.md b/GUI/README.md new file mode 100644 index 0000000..40e93cb --- /dev/null +++ b/GUI/README.md @@ -0,0 +1 @@ +## Contains GUI code \ No newline at end of file diff --git a/GUI/docker-compose.yml b/GUI/docker-compose.yml new file mode 100644 index 0000000..87d6970 --- /dev/null +++ b/GUI/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3.9" +services: + buerokratt_chatbot: + container_name: buerokratt_classifier + build: + context: . + target: web + entrypoint: "/opt/buerokratt-chatbot/rebuild.sh" + ports: + - '3001:3001' diff --git a/GUI/entrypoint.sh b/GUI/entrypoint.sh new file mode 100644 index 0000000..636848f --- /dev/null +++ b/GUI/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# Replace environment variables in the Nginx configuration template +envsubst '$BASE_URL $REACT_APP_RUUTER_API_URL $REACT_APP_RUUTER_V1_PRIVATE_API_URL $REACT_APP_RUUTER_V2_PRIVATE_API_URL $REACT_APP_CUSTOMER_SERVICE_LOGIN $CHOKIDAR_USEPOLLING $PORT' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf + +# Start the Nginx server +nginx -g "daemon off;" diff --git a/GUI/i18n.ts b/GUI/i18n.ts new file mode 100644 index 0000000..6a4593d --- /dev/null +++ b/GUI/i18n.ts @@ -0,0 +1,26 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; + +import commonEN from './translations/en/common.json'; +import commonET from './translations/et/common.json'; + +i18n + .use(LanguageDetector) + .use(initReactI18next) + .init({ + debug: import.meta.env.NODE_ENV === 'development', + fallbackLng: 'et', + supportedLngs: ['et','en'], + resources: { + en: { + common: commonEN, + }, + et: { + common: commonET, + }, + }, + defaultNS: 'common', + }); + +export default i18n; diff --git a/GUI/index.html b/GUI/index.html new file mode 100644 index 0000000..11be2e8 --- /dev/null +++ b/GUI/index.html @@ -0,0 +1,13 @@ + + + + + + + Bürokratt + + +
+ + + diff --git a/GUI/package-lock.json b/GUI/package-lock.json new file mode 100644 index 0000000..436ec9c --- /dev/null +++ b/GUI/package-lock.json @@ -0,0 +1,15860 @@ +{ + "name": "byk-training-module-gui", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "byk-training-module-gui", + "version": "0.0.0", + "dependencies": { + "@buerokratt-ria/styles": "^0.0.1", + "@fontsource/roboto": "^4.5.8", + "@formkit/auto-animate": "^1.0.0-beta.5", + "@fortaine/fetch-event-source": "^3.0.6", + "@radix-ui/react-accessible-icon": "^1.0.1", + "@radix-ui/react-collapsible": "^1.0.1", + "@radix-ui/react-dialog": "^1.0.2", + "@radix-ui/react-popover": "^1.0.2", + "@radix-ui/react-progress": "^1.1.0", + "@radix-ui/react-select": "^1.1.2", + "@radix-ui/react-switch": "^1.0.1", + "@radix-ui/react-tabs": "^1.0.1", + "@radix-ui/react-toast": "^1.1.2", + "@radix-ui/react-tooltip": "^1.0.2", + "@tanstack/match-sorter-utils": "^8.7.2", + "@tanstack/react-query": "^4.36.1", + "@tanstack/react-table": "^8.7.4", + "axios": "^1.2.1", + "clsx": "^1.2.1", + "date-fns": "^2.29.3", + "downshift": "^7.0.5", + "esbuild": "^0.19.5", + "formik": "^2.4.6", + "framer-motion": "^8.5.5", + "howler": "^2.2.4", + "i18next": "^22.4.5", + "i18next-browser-languagedetector": "^7.0.1", + "linkify-react": "^4.1.1", + "linkifyjs": "^4.1.1", + "lodash": "^4.17.21", + "moment": "^2.30.1", + "react": "^18.2.0", + "react-color": "^2.19.3", + "react-cookie": "^4.1.1", + "react-datepicker": "^4.8.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", + "react-dom": "^18.2.0", + "react-hook-form": "^7.52.1", + "react-i18next": "^12.1.1", + "react-icons": "^4.10.1", + "react-idle-timer": "^5.5.2", + "react-modal": "^3.16.1", + "react-redux": "^8.1.1", + "react-router-dom": "^6.5.0", + "react-select": "^5.7.4", + "react-text-selection-popover": "^2.0.2", + "react-textarea-autosize": "^8.4.0", + "reactflow": "^11.4.0", + "regexify-string": "^1.0.19", + "rxjs": "^7.8.1", + "timeago.js": "^4.0.2", + "usehooks-ts": "^2.9.1", + "uuid": "^9.0.0", + "yup": "^1.4.0", + "zustand": "^4.4.4" + }, + "devDependencies": { + "@types/howler": "^2.2.11", + "@types/lodash": "^4.14.191", + "@types/lodash.debounce": "^4.0.7", + "@types/node": "^18.11.17", + "@types/react": "^18.0.26", + "@types/react-color": "^3.0.6", + "@types/react-datepicker": "^4.8.0", + "@types/react-dom": "^18.0.9", + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "^8.32.1", + "@typescript-eslint/parser": "^8.32.1", + "@vitejs/plugin-react": "^3.0.0", + "eslint": "^8.57.1", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.2", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-typescript": "^0.14.0", + "mocksse": "^1.0.4", + "msw": "^0.49.2", + "prettier": "^2.8.1", + "sass": "^1.57.0", + "typescript": "^4.9.3", + "vite": "^4.0.0", + "vite-plugin-env-compatible": "^1.1.1", + "vite-plugin-svgr": "^2.4.0", + "vite-plugin-transform": "^2.0.1", + "vite-tsconfig-paths": "^4.0.3" + } + }, + "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.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.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/eslint-parser": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.7.tgz", + "integrity": "sha512-SO5E3bVxDuxyNxM5agFv480YA2HO6ohZbGxbazZdIk3KQOPOGVNw6q78I9/lbviIf95eq6tPozeYnJLbjnC8IA==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "dependencies": { + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", + "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", + "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz", + "integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-decorators": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz", + "integrity": "sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz", + "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz", + "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", + "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", + "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz", + "integrity": "sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", + "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", + "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz", + "integrity": "sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz", + "integrity": "sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.7.tgz", + "integrity": "sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.7", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.7", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.7", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@buerokratt-ria/styles": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@buerokratt-ria/styles/-/styles-0.0.1.tgz", + "integrity": "sha512-bSj7WsdQO4P/43mRgsa5sDEwBuOebXcl3+Peur8NwToqczqsTMbXSO5P6xyXHoTnHWt082PhT8ht7OAgtFSzfw==" + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/@emotion/babel-plugin/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/serialize/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "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.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "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/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/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/@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, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", + "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", + "dependencies": { + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz", + "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", + "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", + "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" + }, + "node_modules/@fontsource/roboto": { + "version": "4.5.8", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.8.tgz", + "integrity": "sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA==" + }, + "node_modules/@formkit/auto-animate": { + "version": "1.0.0-pre-alpha.3", + "resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-pre-alpha.3.tgz", + "integrity": "sha512-lMVZ3LFUIu0RIxCEwmV8nUUJQ46M2bv2NDU3hrhZivViuR1EheC8Mj5sx/ACqK5QLK8XB8z7GDIZBUGdU/9OZQ==", + "peerDependencies": { + "react": "^16.8.0", + "vue": "^3.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@fortaine/fetch-event-source": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@fortaine/fetch-event-source/-/fetch-event-source-3.0.6.tgz", + "integrity": "sha512-621GAuLMvKtyZQ3IA6nlDWhV1V/7PGOTNIGLUifxt0KzM+dZIweJ6F3XvQF3QnqeNfS1N7WQ0Kil1Di/lhChEw==", + "engines": { + "node": ">=16.15" + } + }, + "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, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "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, + "license": "BSD-3-Clause" + }, + "node_modules/@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "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==", + "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==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "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==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@lezer/common": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" + }, + "node_modules/@lezer/lr": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.1.tgz", + "integrity": "sha512-CHsKq8DMKBf9b3yXPDIU4DbH+ZJd/sJdYOW2llbW/HudP5u0VS6Bfq1hLYfgU7uAYGFIyGGQIsSOXGPEErZiJw==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lmdb/lmdb-darwin-arm64": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.8.5.tgz", + "integrity": "sha512-KPDeVScZgA1oq0CiPBcOa3kHIqU+pTOwRFDIhxvmf8CTNvqdZQYp5cCKW0bUk69VygB2PuTiINFWbY78aR2pQw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-darwin-x64": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.8.5.tgz", + "integrity": "sha512-w/sLhN4T7MW1nB3R/U8WK5BgQLz904wh+/SmA2jD8NnF7BLLoUgflCNxOeSPOWp8geP6nP/+VjWzZVip7rZ1ug==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.8.5.tgz", + "integrity": "sha512-c0TGMbm2M55pwTDIfkDLB6BpIsgxV4PjYck2HiOX+cy/JWiBXz32lYbarPqejKs9Flm7YVAKSILUducU9g2RVg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm64": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.8.5.tgz", + "integrity": "sha512-vtbZRHH5UDlL01TT5jB576Zox3+hdyogvpcbvVJlmU5PdL3c5V7cj1EODdh1CHPksRl+cws/58ugEHi8bcj4Ww==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-x64": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.8.5.tgz", + "integrity": "sha512-Xkc8IUx9aEhP0zvgeKy7IQ3ReX2N8N1L0WPcQwnZweWmOuKfwpS3GRIYqLtK5za/w3E60zhFfNdS+3pBZPytqQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-win32-x64": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.8.5.tgz", + "integrity": "sha512-4wvrf5BgnR8RpogHhtpCPJMKBmvyZPhhUtEwMJbXh0ni2BucpfF07jlmyM11zRqQ2XIq6PbC2j7W7UCCcm1rRQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@mischnic/json-sourcemap": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.1.tgz", + "integrity": "sha512-iA7+tyVqfrATAIsIRWQG+a7ZLLD0VaOCKV2Wd/v4mqIU3J9c4jx9p7S0nw1XH3gJCKNBOOwACOPYYSUu9pgT+w==", + "dependencies": { + "@lezer/common": "^1.0.0", + "@lezer/lr": "^1.0.0", + "json5": "^2.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "dependencies": { + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz", + "integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==", + "dependencies": { + "@motionone/animation": "^10.18.0", + "@motionone/generators": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "dependencies": { + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "dependencies": { + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==" + }, + "node_modules/@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "dependencies": { + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@mswjs/cookies": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.2.tgz", + "integrity": "sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==", + "dev": true, + "dependencies": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.17.10", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.17.10.tgz", + "integrity": "sha512-N8x7eSLGcmUFNWZRxT1vsHvypzIRgQYdG0rJey/rZCy6zT/30qDt8Joj7FxzGNLSwXbeZqJOMqDurp7ra4hgbw==", + "dev": true, + "dependencies": { + "@open-draft/until": "^1.0.3", + "@types/debug": "^4.1.7", + "@xmldom/xmldom": "^0.8.3", + "debug": "^4.3.3", + "headers-polyfill": "3.2.5", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4", + "web-encoding": "^1.1.5" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors/node_modules/headers-polyfill": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.2.5.tgz", + "integrity": "sha512-tUCGvt191vNSQgttSyJoibR+VO+I6+iCHIUdhzEMJKE+EAL8BwCN7fUOZlY4ofOelNHsK+gEjxB/B+9N3EWtdA==", + "dev": true + }, + "node_modules/@mswjs/interceptors/node_modules/strict-event-emitter": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.8.tgz", + "integrity": "sha512-KDf/ujU8Zud3YaLtMCcTI4xkZlZVIYxTLr+XIULexP+77EEVWixeXroLUXQXiVtH4XH2W7jr/3PT1v3zBuvc3A==", + "dev": true, + "dependencies": { + "events": "^3.3.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "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/@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==", + "dev": true + }, + "node_modules/@parcel/bundler-default": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.12.0.tgz", + "integrity": "sha512-3ybN74oYNMKyjD6V20c9Gerdbh7teeNvVMwIoHIQMzuIFT6IGX53PyOLlOKRLbjxMc0TMimQQxIt2eQqxR5LsA==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/graph": "3.2.0", + "@parcel/plugin": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/utils": "2.12.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/cache": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.12.0.tgz", + "integrity": "sha512-FX5ZpTEkxvq/yvWklRHDESVRz+c7sLTXgFuzz6uEnBcXV38j6dMSikflNpHA6q/L4GKkCqRywm9R6XQwhwIMyw==", + "dependencies": { + "@parcel/fs": "2.12.0", + "@parcel/logger": "2.12.0", + "@parcel/utils": "2.12.0", + "lmdb": "2.8.5" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@parcel/codeframe": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.12.0.tgz", + "integrity": "sha512-v2VmneILFiHZJTxPiR7GEF1wey1/IXPdZMcUlNXBiPZyWDfcuNgGGVQkx/xW561rULLIvDPharOMdxz5oHOKQg==", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/codeframe/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@parcel/codeframe/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@parcel/codeframe/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@parcel/codeframe/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@parcel/codeframe/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/codeframe/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/compressor-raw": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.12.0.tgz", + "integrity": "sha512-h41Q3X7ZAQ9wbQ2csP8QGrwepasLZdXiuEdpUryDce6rF9ZiHoJ97MRpdLxOhOPyASTw/xDgE1xyaPQr0Q3f5A==", + "dependencies": { + "@parcel/plugin": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/config-default": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.12.0.tgz", + "integrity": "sha512-dPNe2n9eEsKRc1soWIY0yToMUPirPIa2QhxcCB3Z5RjpDGIXm0pds+BaiqY6uGLEEzsjhRO0ujd4v2Rmm0vuFg==", + "dependencies": { + "@parcel/bundler-default": "2.12.0", + "@parcel/compressor-raw": "2.12.0", + "@parcel/namer-default": "2.12.0", + "@parcel/optimizer-css": "2.12.0", + "@parcel/optimizer-htmlnano": "2.12.0", + "@parcel/optimizer-image": "2.12.0", + "@parcel/optimizer-svgo": "2.12.0", + "@parcel/optimizer-swc": "2.12.0", + "@parcel/packager-css": "2.12.0", + "@parcel/packager-html": "2.12.0", + "@parcel/packager-js": "2.12.0", + "@parcel/packager-raw": "2.12.0", + "@parcel/packager-svg": "2.12.0", + "@parcel/packager-wasm": "2.12.0", + "@parcel/reporter-dev-server": "2.12.0", + "@parcel/resolver-default": "2.12.0", + "@parcel/runtime-browser-hmr": "2.12.0", + "@parcel/runtime-js": "2.12.0", + "@parcel/runtime-react-refresh": "2.12.0", + "@parcel/runtime-service-worker": "2.12.0", + "@parcel/transformer-babel": "2.12.0", + "@parcel/transformer-css": "2.12.0", + "@parcel/transformer-html": "2.12.0", + "@parcel/transformer-image": "2.12.0", + "@parcel/transformer-js": "2.12.0", + "@parcel/transformer-json": "2.12.0", + "@parcel/transformer-postcss": "2.12.0", + "@parcel/transformer-posthtml": "2.12.0", + "@parcel/transformer-raw": "2.12.0", + "@parcel/transformer-react-refresh-wrap": "2.12.0", + "@parcel/transformer-svg": "2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@parcel/core": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.12.0.tgz", + "integrity": "sha512-s+6pwEj+GfKf7vqGUzN9iSEPueUssCCQrCBUlcAfKrJe0a22hTUCjewpB0I7lNrCIULt8dkndD+sMdOrXsRl6Q==", + "dependencies": { + "@mischnic/json-sourcemap": "^0.1.0", + "@parcel/cache": "2.12.0", + "@parcel/diagnostic": "2.12.0", + "@parcel/events": "2.12.0", + "@parcel/fs": "2.12.0", + "@parcel/graph": "3.2.0", + "@parcel/logger": "2.12.0", + "@parcel/package-manager": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/profiler": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "@parcel/workers": "2.12.0", + "abortcontroller-polyfill": "^1.1.9", + "base-x": "^3.0.8", + "browserslist": "^4.6.6", + "clone": "^2.1.1", + "dotenv": "^7.0.0", + "dotenv-expand": "^5.1.0", + "json5": "^2.2.0", + "msgpackr": "^1.9.9", + "nullthrows": "^1.1.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/core/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/diagnostic": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.12.0.tgz", + "integrity": "sha512-8f1NOsSFK+F4AwFCKynyIu9Kr/uWHC+SywAv4oS6Bv3Acig0gtwUjugk0C9UaB8ztBZiW5TQZhw+uPZn9T/lJA==", + "dependencies": { + "@mischnic/json-sourcemap": "^0.1.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/events": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.12.0.tgz", + "integrity": "sha512-nmAAEIKLjW1kB2cUbCYSmZOGbnGj8wCzhqnK727zCCWaA25ogzAtt657GPOeFyqW77KyosU728Tl63Fc8hphIA==", + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/fs": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.12.0.tgz", + "integrity": "sha512-NnFkuvou1YBtPOhTdZr44WN7I60cGyly2wpHzqRl62yhObyi1KvW0SjwOMa0QGNcBOIzp4G0CapoZ93hD0RG5Q==", + "dependencies": { + "@parcel/rust": "2.12.0", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "@parcel/watcher": "^2.0.7", + "@parcel/workers": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@parcel/graph": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-3.2.0.tgz", + "integrity": "sha512-xlrmCPqy58D4Fg5umV7bpwDx5Vyt7MlnQPxW68vae5+BA4GSWetfZt+Cs5dtotMG2oCHzZxhIPt7YZ7NRyQzLA==", + "dependencies": { + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/logger": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.12.0.tgz", + "integrity": "sha512-cJ7Paqa7/9VJ7C+KwgJlwMqTQBOjjn71FbKk0G07hydUEBISU2aDfmc/52o60ErL9l+vXB26zTrIBanbxS8rVg==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/events": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/markdown-ansi": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.12.0.tgz", + "integrity": "sha512-WZz3rzL8k0H3WR4qTHX6Ic8DlEs17keO9gtD4MNGyMNQbqQEvQ61lWJaIH0nAtgEetu0SOITiVqdZrb8zx/M7w==", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/markdown-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@parcel/markdown-ansi/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@parcel/markdown-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@parcel/markdown-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@parcel/markdown-ansi/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/markdown-ansi/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/namer-default": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.12.0.tgz", + "integrity": "sha512-9DNKPDHWgMnMtqqZIMiEj/R9PNWW16lpnlHjwK3ciRlMPgjPJ8+UNc255teZODhX0T17GOzPdGbU/O/xbxVPzA==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/node-resolver-core": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-3.3.0.tgz", + "integrity": "sha512-rhPW9DYPEIqQBSlYzz3S0AjXxjN6Ub2yS6tzzsW/4S3Gpsgk/uEq4ZfxPvoPf/6TgZndVxmKwpmxaKtGMmf3cA==", + "dependencies": { + "@mischnic/json-sourcemap": "^0.1.0", + "@parcel/diagnostic": "2.12.0", + "@parcel/fs": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/utils": "2.12.0", + "nullthrows": "^1.1.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/node-resolver-core/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/optimizer-css": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.12.0.tgz", + "integrity": "sha512-ifbcC97fRzpruTjaa8axIFeX4MjjSIlQfem3EJug3L2AVqQUXnM1XO8L0NaXGNLTW2qnh1ZjIJ7vXT/QhsphsA==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.12.0", + "browserslist": "^4.6.6", + "lightningcss": "^1.22.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-htmlnano": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.12.0.tgz", + "integrity": "sha512-MfPMeCrT8FYiOrpFHVR+NcZQlXAptK2r4nGJjfT+ndPBhEEZp4yyL7n1y7HfX9geg5altc4WTb4Gug7rCoW8VQ==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "htmlnano": "^2.0.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "svgo": "^2.4.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-image": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.12.0.tgz", + "integrity": "sha512-bo1O7raeAIbRU5nmNVtx8divLW9Xqn0c57GVNGeAK4mygnQoqHqRZ0mR9uboh64pxv6ijXZHPhKvU9HEpjPjBQ==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/utils": "2.12.0", + "@parcel/workers": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@parcel/optimizer-svgo": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.12.0.tgz", + "integrity": "sha512-Kyli+ZZXnoonnbeRQdoWwee9Bk2jm/49xvnfb+2OO8NN0d41lblBoRhOyFiScRnJrw7eVl1Xrz7NTkXCIO7XFQ==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "svgo": "^2.4.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-swc": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-swc/-/optimizer-swc-2.12.0.tgz", + "integrity": "sha512-iBi6LZB3lm6WmbXfzi8J3DCVPmn4FN2lw7DGXxUXu7MouDPVWfTsM6U/5TkSHJRNRogZ2gqy5q9g34NPxHbJcw==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.12.0", + "@swc/core": "^1.3.36", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/package-manager": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.12.0.tgz", + "integrity": "sha512-0nvAezcjPx9FT+hIL+LS1jb0aohwLZXct7jAh7i0MLMtehOi0z1Sau+QpgMlA9rfEZZ1LIeFdnZZwqSy7Ccspw==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/fs": "2.12.0", + "@parcel/logger": "2.12.0", + "@parcel/node-resolver-core": "3.3.0", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "@parcel/workers": "2.12.0", + "@swc/core": "^1.3.36", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@parcel/package-manager/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/packager-css": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.12.0.tgz", + "integrity": "sha512-j3a/ODciaNKD19IYdWJT+TP+tnhhn5koBGBWWtrKSu0UxWpnezIGZetit3eE+Y9+NTePalMkvpIlit2eDhvfJA==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.12.0", + "lightningcss": "^1.22.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-html": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.12.0.tgz", + "integrity": "sha512-PpvGB9hFFe+19NXGz2ApvPrkA9GwEqaDAninT+3pJD57OVBaxB8U+HN4a5LICKxjUppPPqmrLb6YPbD65IX4RA==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-js": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.12.0.tgz", + "integrity": "sha512-viMF+FszITRRr8+2iJyk+4ruGiL27Y6AF7hQ3xbJfzqnmbOhGFtLTQwuwhOLqN/mWR2VKdgbLpZSarWaO3yAMg==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "globals": "^13.2.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-js/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@parcel/packager-js/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@parcel/packager-raw": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.12.0.tgz", + "integrity": "sha512-tJZqFbHqP24aq1F+OojFbQIc09P/u8HAW5xfndCrFnXpW4wTgM3p03P0xfw3gnNq+TtxHJ8c3UFE5LnXNNKhYA==", + "dependencies": { + "@parcel/plugin": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-svg": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.12.0.tgz", + "integrity": "sha512-ldaGiacGb2lLqcXas97k8JiZRbAnNREmcvoY2W2dvW4loVuDT9B9fU777mbV6zODpcgcHWsLL3lYbJ5Lt3y9cg==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "posthtml": "^0.16.4" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-wasm": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.12.0.tgz", + "integrity": "sha512-fYqZzIqO9fGYveeImzF8ll6KRo2LrOXfD+2Y5U3BiX/wp9wv17dz50QLDQm9hmTcKGWxK4yWqKQh+Evp/fae7A==", + "dependencies": { + "@parcel/plugin": "2.12.0" + }, + "engines": { + "node": ">=12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/plugin": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.12.0.tgz", + "integrity": "sha512-nc/uRA8DiMoe4neBbzV6kDndh/58a4wQuGKw5oEoIwBCHUvE2W8ZFSu7ollSXUGRzfacTt4NdY8TwS73ScWZ+g==", + "dependencies": { + "@parcel/types": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/profiler": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/profiler/-/profiler-2.12.0.tgz", + "integrity": "sha512-q53fvl5LDcFYzMUtSusUBZSjQrKjMlLEBgKeQHFwkimwR1mgoseaDBDuNz0XvmzDzF1UelJ02TUKCGacU8W2qA==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/events": "2.12.0", + "chrome-trace-event": "^1.0.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/reporter-cli": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.12.0.tgz", + "integrity": "sha512-TqKsH4GVOLPSCanZ6tcTPj+rdVHERnt5y4bwTM82cajM21bCX1Ruwp8xOKU+03091oV2pv5ieB18pJyRF7IpIw==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "chalk": "^4.1.0", + "term-size": "^2.2.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/reporter-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@parcel/reporter-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@parcel/reporter-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@parcel/reporter-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@parcel/reporter-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/reporter-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/reporter-dev-server": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.12.0.tgz", + "integrity": "sha512-tIcDqRvAPAttRlTV28dHcbWT5K2r/MBFks7nM4nrEDHWtnrCwimkDmZTc1kD8QOCCjGVwRHcQybpHvxfwol6GA==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/reporter-tracer": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-tracer/-/reporter-tracer-2.12.0.tgz", + "integrity": "sha512-g8rlu9GxB8Ut/F8WGx4zidIPQ4pcYFjU9bZO+fyRIPrSUFH2bKijCnbZcr4ntqzDGx74hwD6cCG4DBoleq2UlQ==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "chrome-trace-event": "^1.0.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/resolver-default": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.12.0.tgz", + "integrity": "sha512-uuhbajTax37TwCxu7V98JtRLiT6hzE4VYSu5B7Qkauy14/WFt2dz6GOUXPgVsED569/hkxebPx3KCMtZW6cHHA==", + "dependencies": { + "@parcel/node-resolver-core": "3.3.0", + "@parcel/plugin": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-browser-hmr": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.12.0.tgz", + "integrity": "sha512-4ZLp2FWyD32r0GlTulO3+jxgsA3oO1P1b5oO2IWuWilfhcJH5LTiazpL5YdusUjtNn9PGN6QLAWfxmzRIfM+Ow==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-js": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.12.0.tgz", + "integrity": "sha512-sBerP32Z1crX5PfLNGDSXSdqzlllM++GVnVQVeM7DgMKS8JIFG3VLi28YkX+dYYGtPypm01JoIHCkvwiZEcQJg==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-react-refresh": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.12.0.tgz", + "integrity": "sha512-SCHkcczJIDFTFdLTzrHTkQ0aTrX3xH6jrA4UsCBL6ji61+w+ohy4jEEe9qCgJVXhnJfGLE43HNXek+0MStX+Mw==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "react-error-overlay": "6.0.9", + "react-refresh": "^0.9.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-react-refresh/node_modules/react-refresh": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", + "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@parcel/runtime-service-worker": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.12.0.tgz", + "integrity": "sha512-BXuMBsfiwpIEnssn+jqfC3jkgbS8oxeo3C7xhSQsuSv+AF2FwY3O3AO1c1RBskEW3XrBLNINOJujroNw80VTKA==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/rust": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/rust/-/rust-2.12.0.tgz", + "integrity": "sha512-005cldMdFZFDPOjbDVEXcINQ3wT4vrxvSavRWI3Az0e3E18exO/x/mW9f648KtXugOXMAqCEqhFHcXECL9nmMw==", + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/source-map": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", + "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": "^12.18.3 || >=14" + } + }, + "node_modules/@parcel/transformer-babel": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.12.0.tgz", + "integrity": "sha512-zQaBfOnf/l8rPxYGnsk/ufh/0EuqvmnxafjBIpKZ//j6rGylw5JCqXSb1QvvAqRYruKeccxGv7+HrxpqKU6V4A==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.12.0", + "browserslist": "^4.6.6", + "json5": "^2.2.0", + "nullthrows": "^1.1.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-babel/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/transformer-css": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.12.0.tgz", + "integrity": "sha512-vXhOqoAlQGATYyQ433Z1DXKmiKmzOAUmKysbYH3FD+LKEKLMEl/pA14goqp00TW+A/EjtSKKyeMyHlMIIUqj4Q==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.12.0", + "browserslist": "^4.6.6", + "lightningcss": "^1.22.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-html": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.12.0.tgz", + "integrity": "sha512-5jW4dFFBlYBvIQk4nrH62rfA/G/KzVzEDa6S+Nne0xXhglLjkm64Ci9b/d4tKZfuGWUbpm2ASAq8skti/nfpXw==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/rust": "2.12.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^7.5.2", + "srcset": "4" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-html/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/transformer-image": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.12.0.tgz", + "integrity": "sha512-8hXrGm2IRII49R7lZ0RpmNk27EhcsH+uNKsvxuMpXPuEnWgC/ha/IrjaI29xCng1uGur74bJF43NUSQhR4aTdw==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "@parcel/workers": "2.12.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@parcel/transformer-js": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.12.0.tgz", + "integrity": "sha512-OSZpOu+FGDbC/xivu24v092D9w6EGytB3vidwbdiJ2FaPgfV7rxS0WIUjH4I0OcvHAcitArRXL0a3+HrNTdQQw==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.12.0", + "@parcel/workers": "2.12.0", + "@swc/helpers": "^0.5.0", + "browserslist": "^4.6.6", + "nullthrows": "^1.1.1", + "regenerator-runtime": "^0.13.7", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@parcel/transformer-js/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/@parcel/transformer-js/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/transformer-json": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.12.0.tgz", + "integrity": "sha512-Utv64GLRCQILK5r0KFs4o7I41ixMPllwOLOhkdjJKvf1hZmN6WqfOmB1YLbWS/y5Zb/iB52DU2pWZm96vLFQZQ==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "json5": "^2.2.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-postcss": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.12.0.tgz", + "integrity": "sha512-FZqn+oUtiLfPOn67EZxPpBkfdFiTnF4iwiXPqvst3XI8H+iC+yNgzmtJkunOOuylpYY6NOU5jT8d7saqWSDv2Q==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/utils": "2.12.0", + "clone": "^2.1.1", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-postcss/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/transformer-posthtml": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.12.0.tgz", + "integrity": "sha512-z6Z7rav/pcaWdeD+2sDUcd0mmNZRUvtHaUGa50Y2mr+poxrKilpsnFMSiWBT+oOqPt7j71jzDvrdnAF4XkCljg==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-posthtml/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/transformer-raw": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.12.0.tgz", + "integrity": "sha512-Ht1fQvXxix0NncdnmnXZsa6hra20RXYh1VqhBYZLsDfkvGGFnXIgO03Jqn4Z8MkKoa0tiNbDhpKIeTjyclbBxQ==", + "dependencies": { + "@parcel/plugin": "2.12.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-react-refresh-wrap": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.12.0.tgz", + "integrity": "sha512-GE8gmP2AZtkpBIV5vSCVhewgOFRhqwdM5Q9jNPOY5PKcM3/Ff0qCqDiTzzGLhk0/VMBrdjssrfZkVx6S/lHdJw==", + "dependencies": { + "@parcel/plugin": "2.12.0", + "@parcel/utils": "2.12.0", + "react-refresh": "^0.9.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-react-refresh-wrap/node_modules/react-refresh": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", + "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@parcel/transformer-svg": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.12.0.tgz", + "integrity": "sha512-cZJqGRJ4JNdYcb+vj94J7PdOuTnwyy45dM9xqbIMH+HSiiIkfrMsdEwYft0GTyFTdsnf+hdHn3tau7Qa5hhX+A==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/plugin": "2.12.0", + "@parcel/rust": "2.12.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^7.5.2" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-svg/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@parcel/types": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.12.0.tgz", + "integrity": "sha512-8zAFiYNCwNTQcglIObyNwKfRYQK5ELlL13GuBOrSMxueUiI5ylgsGbTS1N7J3dAGZixHO8KhHGv5a71FILn9rQ==", + "dependencies": { + "@parcel/cache": "2.12.0", + "@parcel/diagnostic": "2.12.0", + "@parcel/fs": "2.12.0", + "@parcel/package-manager": "2.12.0", + "@parcel/source-map": "^2.1.1", + "@parcel/workers": "2.12.0", + "utility-types": "^3.10.0" + } + }, + "node_modules/@parcel/utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.12.0.tgz", + "integrity": "sha512-z1JhLuZ8QmDaYoEIuUCVZlhcFrS7LMfHrb2OCRui5SQFntRWBH2fNM6H/fXXUkT9SkxcuFP2DUA6/m4+Gkz72g==", + "dependencies": { + "@parcel/codeframe": "2.12.0", + "@parcel/diagnostic": "2.12.0", + "@parcel/logger": "2.12.0", + "@parcel/markdown-ansi": "2.12.0", + "@parcel/rust": "2.12.0", + "@parcel/source-map": "^2.1.1", + "chalk": "^4.1.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@parcel/utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@parcel/utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@parcel/utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@parcel/utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", + "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.4.1", + "@parcel/watcher-darwin-arm64": "2.4.1", + "@parcel/watcher-darwin-x64": "2.4.1", + "@parcel/watcher-freebsd-x64": "2.4.1", + "@parcel/watcher-linux-arm-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-musl": "2.4.1", + "@parcel/watcher-linux-x64-glibc": "2.4.1", + "@parcel/watcher-linux-x64-musl": "2.4.1", + "@parcel/watcher-win32-arm64": "2.4.1", + "@parcel/watcher-win32-ia32": "2.4.1", + "@parcel/watcher-win32-x64": "2.4.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", + "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", + "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", + "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", + "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", + "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", + "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", + "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", + "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", + "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", + "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", + "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", + "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/workers": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.12.0.tgz", + "integrity": "sha512-zv5We5Jmb+ZWXlU6A+AufyjY4oZckkxsZ8J4dvyWL0W8IQvGO1JB4FGeryyttzQv3RM3OxcN/BpTGPiDG6keBw==", + "dependencies": { + "@parcel/diagnostic": "2.12.0", + "@parcel/logger": "2.12.0", + "@parcel/profiler": "2.12.0", + "@parcel/types": "2.12.0", + "@parcel/utils": "2.12.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.12.0" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", + "integrity": "sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-accessible-icon": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.0.3.tgz", + "integrity": "sha512-duVGKeWPSUILr/MdlPxV+GeULTc2rS1aihGdQ3N2qCUPMgxYLxvAsHJM3mCVLF8d5eK+ympmB22mb1F3a5biNw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-visually-hidden": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", + "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", + "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", + "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", + "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.7.tgz", + "integrity": "sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", + "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.0.tgz", + "integrity": "sha512-aSzvnYpP725CROcxAOEBVZZSIQVQdHgBr2QQFKySsaD14u8dNT0batuXI+AAGDdAHfXH8rbnHmjYFqVJ21KkRg==", + "dependencies": { + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", + "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.2.tgz", + "integrity": "sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/number": "1.0.1", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.4", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.3", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.2", + "@radix-ui/react-portal": "1.0.3", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz", + "integrity": "sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz", + "integrity": "sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", + "integrity": "sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-portal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz", + "integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz", + "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.4.tgz", + "integrity": "sha512-egZfYY/+wRNCflXNHx+dePvnz9FbmssDTJBtgRfDY7e8SE5oIo3Py2eCB1ckAbh1Q7cQ/6yJZThJ++sgbxibog==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toast": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.1.5.tgz", + "integrity": "sha512-fRLn227WHIBRSzuRzGJ8W+5YALxofH23y0MlPLddaIpLpCDqdE0NZlS2NRQDRiptfxDeeCjgFIpexB1/zkxDlw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", + "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz", + "integrity": "sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", + "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", + "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@react-dnd/asap": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" + }, + "node_modules/@react-dnd/invariant": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + }, + "node_modules/@react-dnd/shallowequal": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + }, + "node_modules/@reactflow/background": { + "version": "11.3.13", + "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.13.tgz", + "integrity": "sha512-hkvpVEhgvfTDyCvdlitw4ioKCYLaaiRXnuEG+1QM3Np+7N1DiWF1XOv5I8AFyNoJL07yXEkbECUTsHvkBvcG5A==", + "dependencies": { + "@reactflow/core": "11.11.3", + "classcat": "^5.0.3", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/controls": { + "version": "11.2.13", + "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.13.tgz", + "integrity": "sha512-3xgEg6ALIVkAQCS4NiBjb7ad8Cb3D8CtA7Vvl4Hf5Ar2PIVs6FOaeft9s2iDZGtsWP35ECDYId1rIFVhQL8r+A==", + "dependencies": { + "@reactflow/core": "11.11.3", + "classcat": "^5.0.3", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/core": { + "version": "11.11.3", + "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.11.3.tgz", + "integrity": "sha512-+adHdUa7fJSEM93fWfjQwyWXeI92a1eLKwWbIstoCakHpL8UjzwhEh6sn+mN2h/59MlVI7Ehr1iGTt3MsfcIFA==", + "dependencies": { + "@types/d3": "^7.4.0", + "@types/d3-drag": "^3.0.1", + "@types/d3-selection": "^3.0.3", + "@types/d3-zoom": "^3.0.1", + "classcat": "^5.0.3", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/minimap": { + "version": "11.7.13", + "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.13.tgz", + "integrity": "sha512-m2MvdiGSyOu44LEcERDEl1Aj6x//UQRWo3HEAejNU4HQTlJnYrSN8tgrYF8TxC1+c/9UdyzQY5VYgrTwW4QWdg==", + "dependencies": { + "@reactflow/core": "11.11.3", + "@types/d3-selection": "^3.0.3", + "@types/d3-zoom": "^3.0.1", + "classcat": "^5.0.3", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/node-resizer": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.13.tgz", + "integrity": "sha512-X7ceQ2s3jFLgbkg03n2RYr4hm3jTVrzkW2W/8ANv/SZfuVmF8XJxlERuD8Eka5voKqLda0ywIZGAbw9GoHLfUQ==", + "dependencies": { + "@reactflow/core": "11.11.3", + "classcat": "^5.0.4", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/node-toolbar": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.13.tgz", + "integrity": "sha512-aknvNICO10uWdthFSpgD6ctY/CTBeJUMV9co8T9Ilugr08Nb89IQ4uD0dPmr031ewMQxixtYIkw+sSDDzd2aaQ==", + "dependencies": { + "@reactflow/core": "11.11.3", + "classcat": "^5.0.3", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@remix-run/router": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz", + "integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", + "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", + "dev": true + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", + "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", + "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", + "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", + "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", + "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", + "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", + "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", + "@svgr/babel-plugin-remove-jsx-attribute": "*", + "@svgr/babel-plugin-remove-jsx-empty-expression": "*", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", + "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", + "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", + "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", + "@svgr/babel-plugin-transform-svg-component": "^6.5.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", + "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", + "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.0", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", + "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/hast-util-to-babel-ast": "^6.5.1", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "^6.0.0" + } + }, + "node_modules/@swc/core": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.28.tgz", + "integrity": "sha512-muCdNIqOTURUgYeyyOLYE3ShL8SZO6dw6bhRm6dCvxWzCZOncPc5fB0kjcPXTML+9KJoHL7ks5xg+vsQK+v6ig==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.8" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.5.28", + "@swc/core-darwin-x64": "1.5.28", + "@swc/core-linux-arm-gnueabihf": "1.5.28", + "@swc/core-linux-arm64-gnu": "1.5.28", + "@swc/core-linux-arm64-musl": "1.5.28", + "@swc/core-linux-x64-gnu": "1.5.28", + "@swc/core-linux-x64-musl": "1.5.28", + "@swc/core-win32-arm64-msvc": "1.5.28", + "@swc/core-win32-ia32-msvc": "1.5.28", + "@swc/core-win32-x64-msvc": "1.5.28" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.28.tgz", + "integrity": "sha512-sP6g63ybzIdOWNDbn51tyHN8EMt7Mb4RMeHQEsXB7wQfDvzhpWB+AbfK6Gs3Q8fwP/pmWIrWW9csKOc1K2Mmkg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.28.tgz", + "integrity": "sha512-Bd/agp/g7QocQG5AuorOzSC78t8OzeN+pCN/QvJj1CvPhvppjJw6e1vAbOR8vO2vvGi2pvtf3polrYQStJtSiA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.28.tgz", + "integrity": "sha512-Wr3TwPGIveS9/OBWm0r9VAL8wkCR0zQn46J8K01uYCmVhUNK3Muxjs0vQBZaOrGu94mqbj9OXY+gB3W7aDvGdA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.28.tgz", + "integrity": "sha512-8G1ZwVTuLgTAVTMPD+M97eU6WeiRIlGHwKZ5fiJHPBcz1xqIC7jQcEh7XBkobkYoU5OILotls3gzjRt8CMNyDQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.28.tgz", + "integrity": "sha512-0Ajdzb5Fzvz+XUbN5ESeHAz9aHHSYiQcm+vmsDi0TtPHmsalfnqEPZmnK0zPALPJPLQP2dDo4hELeDg3/c3xgA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.28.tgz", + "integrity": "sha512-ueQ9VejnQUM2Pt+vT0IAKoF4vYBWUP6n1KHGdILpoGe3LuafQrqu7RoyQ15C7/AYii7hAeNhTFdf6gLbg8cjFg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.28.tgz", + "integrity": "sha512-G5th8Mg0az8CbY4GQt9/m5hg2Y0kGIwvQBeVACuLQB6q2Y4txzdiTpjmFqUUhEvvl7Klyx1IHvNhfXs3zpt7PA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.28.tgz", + "integrity": "sha512-JezwCGavZ7CkNXx4yInI4kpb71L0zxzxA9BFlmnsGKEEjVQcKc3hFpmIzfFVs+eotlBUwDNb0+Yo9m6Cb7lllA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.28.tgz", + "integrity": "sha512-q8tW5J4RkOkl7vYShnWS//VAb2Ngolfm9WOMaF2GRJUr2Y/Xeb/+cNjdsNOqea2BzW049D5vdP7XPmir3/zUZw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.28.tgz", + "integrity": "sha512-jap6EiB3wG1YE1hyhNr9KLPpH4PGm+5tVMfN0l7fgKtV0ikgpcEN/YF94tru+z5m2HovqYW009+Evq9dcVGmpg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", + "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@swc/types": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.8.tgz", + "integrity": "sha512-RNFA3+7OJFNYY78x0FYwi1Ow+iF1eF5WvmfY1nXPOEH4R2p/D4Cr1vzje7dNAI2aLFqpv8Wyz4oKSWqIZArpQA==", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tanstack/match-sorter-utils": { + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.15.1.tgz", + "integrity": "sha512-PnVV3d2poenUM31ZbZi/yXkBu3J7kd5k2u51CGwwNojag451AjTH9N6n41yjXz2fpLeewleyLBmNS6+HcGDlXw==", + "dependencies": { + "remove-accents": "0.5.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-core": { + "version": "4.36.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.36.1.tgz", + "integrity": "sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "4.36.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.36.1.tgz", + "integrity": "sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.36.1", + "use-sync-external-store": "^1.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@tanstack/react-table": { + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.17.3.tgz", + "integrity": "sha512-5gwg5SvPD3lNAXPuJJz1fOCEZYk9/GeBFH3w/hCgnfyszOIzwkwgp5I7Q4MJtn0WECp84b5STQUDdmvGi8m3nA==", + "dependencies": { + "@tanstack/table-core": "8.17.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.17.3.tgz", + "integrity": "sha512-mPBodDGVL+fl6d90wUREepHa/7lhsghg2A3vFpakEhrhtbIlgNAZiMr7ccTgak5qbHqF14Fwy+W1yFWQt+WmYQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", + "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.9.tgz", + "integrity": "sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", + "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.10.tgz", + "integrity": "sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.8.tgz", + "integrity": "sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "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.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/howler": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/@types/howler/-/howler-2.2.11.tgz", + "integrity": "sha512-7aBoUL6RbSIrqKnpEgfa1wSNUBK06mn08siP2QI0zYk7MXfEJAaORc4tohamQYqCqVESoDyRWSdQn2BOKWj2Qw==", + "dev": true + }, + "node_modules/@types/js-levenshtein": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.3.tgz", + "integrity": "sha512-jd+Q+sD20Qfu9e2aEXogiO3vpOC1PYJOUdyN9gvs4Qrvkg4wF43L5OhqrPeokdv8TL0/mXoYfpkcoGZMNN2pkQ==", + "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/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/lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==", + "dev": true + }, + "node_modules/@types/lodash.debounce": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.9.tgz", + "integrity": "sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.19.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.34.tgz", + "integrity": "sha512-eXF4pfBNV5DAMKGbI02NnDtWrQ40hAN558/2vvS4gMpMIxaf6JmD7YjnZbq0Q9TDSSkKBamime8ewRoomHdt4g==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-color": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.12.tgz", + "integrity": "sha512-pr3uKE3lSvf7GFo1Rn2K3QktiZQFFrSgSGJ/3iMvSOYWt2pPAJ97rVdVfhWxYJZ8prAEXzoP2XX//3qGSQgu7Q==", + "dev": true, + "dependencies": { + "@types/react": "*", + "@types/reactcss": "*" + } + }, + "node_modules/@types/react-datepicker": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.19.6.tgz", + "integrity": "sha512-uH5fzxt9eXxnc+hDCy/iRSFqU2+9lR/q2lAmaG4WILMai1o3IOdpcV+VSypzBFJLTEC2jrfeDXcdol0CJVMq4g==", + "dev": true, + "dependencies": { + "@popperjs/core": "^2.9.2", + "@types/react": "*", + "date-fns": "^2.0.1", + "react-popper": "^2.2.5" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/reactcss": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.12.tgz", + "integrity": "sha512-BrXUQ86/wbbFiZv8h/Q1/Q1XOsaHneYmCb/tHe9+M8XBAAUc2EHfdY0DY22ZZjVSaXr5ix7j+zsqO2eGZub8lQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "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/set-cookie-parser": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.9.tgz", + "integrity": "sha512-bCorlULvl0xTdjj4BPUHX4cqs9I+go2TfW/7Do1nnFYWS0CPP429Qr1AY42kiFhCwLpvAkWFr1XIBHd8j6/MCQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.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.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "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.1.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.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" + }, + "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.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "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/@typescript-eslint/eslint-plugin/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/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, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "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.9.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "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.1.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.9.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "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/@typescript-eslint/parser/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/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, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/parser/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.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.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" + }, + "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/node_modules/@typescript-eslint/types": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", + "dev": true, + "license": "MIT", + "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/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "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.1.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.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" + }, + "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.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "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/@typescript-eslint/type-utils/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/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, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz", + "integrity": "sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==", + "dev": true, + "dependencies": { + "@babel/core": "^7.20.12", + "@babel/plugin-transform-react-jsx-self": "^7.18.6", + "@babel/plugin-transform-react-jsx-source": "^7.19.6", + "magic-string": "^0.27.0", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.1.0-beta.0" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "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==", + "dev": true, + "optional": true + }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", + "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==" + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "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-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "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==" + }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "license": "Apache-2.0", + "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, + "license": "MIT", + "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-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.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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/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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/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==", + "dev": true, + "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.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", + "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "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, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", + "dev": true + }, + "node_modules/babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "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==", + "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/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "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==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "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.30001629", + "electron-to-chromium": "^1.4.796", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.16" + }, + "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==", + "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": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001632", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz", + "integrity": "sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg==", + "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": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "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/chokidar/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/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/classcat": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", + "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==" + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, + "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/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/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/cliui/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/cliui/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/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "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/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-2.0.4.tgz", + "integrity": "sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==" + }, + "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/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "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/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "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-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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "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/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "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/defaults/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/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, + "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/dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "dependencies": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.0" + } + }, + "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/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "node_modules/downshift": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-7.6.2.tgz", + "integrity": "sha512-iOv+E1Hyt3JDdL9yYcOgW7nZ7GQ2Uz6YbggwXvKUSleetYhU2nXD482Rz6CzvM4lvI1At34BYruKAL4swRGxaA==", + "dependencies": { + "@babel/runtime": "^7.14.8", + "compute-scroll-into-view": "^2.0.4", + "prop-types": "^15.7.2", + "react-is": "^17.0.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.12.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.799", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.799.tgz", + "integrity": "sha512-3D3DwWkRTzrdEpntY0hMLYwj7SeBk1138CkPE8sBDSj3WzrzOiG2rHm3luw8jucpf+WiyLBCZyU9lMHyQI9M9Q==" + }, + "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/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-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, + "license": "MIT", + "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-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "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, + "license": "MIT", + "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-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0" + } + }, + "node_modules/eslint-config-react-app/node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-react-app/node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-react-app/node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-react-app/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, + "license": "MIT", + "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-config-react-app/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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-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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, + "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, + "license": "MIT", + "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/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-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "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, + "license": "MIT", + "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-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "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.9", + "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": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "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/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/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-testing-library": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.1.tgz", + "integrity": "sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.58.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-typescript": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-typescript/-/eslint-plugin-typescript-0.14.0.tgz", + "integrity": "sha512-2u1WnnDF2mkWWgU1lFQ2RjypUlmRoBEvQN02y9u+IL12mjWlkKFGEBnVsjs9Y8190bfPQCvWly1c2rYYUSOxWw==", + "deprecated": "Deprecated: Use @typescript-eslint/eslint-plugin instead", + "dev": true, + "dependencies": { + "requireindex": "~1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "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/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/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/eslint/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/eslint/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/eslint/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/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/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/eslint/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/eslint/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/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.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "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-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "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/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "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.4" + }, + "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.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "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.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formik": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz", + "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/formik/node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, + "node_modules/framer-motion": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-8.5.5.tgz", + "integrity": "sha512-5IDx5bxkjWHWUF3CVJoSyUVOtrbAxtzYBBowRE2uYI/6VYhkEBD+rbTHEGuUmbGHRj6YqqSfoG7Aa1cLyWCrBA==", + "dependencies": { + "@motionone/dom": "^10.15.3", + "hey-listen": "^1.0.8", + "tslib": "^2.4.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^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==", + "dev": true, + "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, + "license": "MIT", + "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/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-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT", + "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/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/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": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/graphql": { + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.2.tgz", + "integrity": "sha512-cvVIBILwuoSyD54U4cF/UXDh5yAobhNV/tPygI4lZhgOIJQE/WLWC4waBRb4I6bDVYb3OVx3lfHbaQOEoUD5sg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "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/headers-polyfill": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.3.0.tgz", + "integrity": "sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ==", + "dev": true + }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/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==" + }, + "node_modules/howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==" + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/htmlnano": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.1.1.tgz", + "integrity": "sha512-kAERyg/LuNZYmdqgCdYvugyLWNFAm8MWXpQMz1pLpetmCbFwoMxvkSoaAMlFrOC4OKTWI4KlZGT/RsNxg4ghOw==", + "dependencies": { + "cosmiconfig": "^9.0.0", + "posthtml": "^0.16.5", + "timsort": "^0.3.0" + }, + "peerDependencies": { + "cssnano": "^7.0.0", + "postcss": "^8.3.11", + "purgecss": "^6.0.0", + "relateurl": "^0.2.7", + "srcset": "5.0.1", + "svgo": "^3.0.2", + "terser": "^5.10.0", + "uncss": "^0.17.3" + }, + "peerDependenciesMeta": { + "cssnano": { + "optional": true + }, + "postcss": { + "optional": true + }, + "purgecss": { + "optional": true + }, + "relateurl": { + "optional": true + }, + "srcset": { + "optional": true + }, + "svgo": { + "optional": true + }, + "terser": { + "optional": true + }, + "uncss": { + "optional": true + } + } + }, + "node_modules/htmlnano/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/i18next": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz", + "integrity": "sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.20.6" + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.1.tgz", + "integrity": "sha512-h/pM34bcH6tbz8WgGXcmWauNpQupCGr25XPp9cZwZInR9XHSjIFDYp1SIok7zSPsTOMxdvuLyu86V+g2Kycnfw==", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "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==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.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==", + "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/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "dev": true + }, + "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==", + "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/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==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/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/inquirer/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/inquirer/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/inquirer/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/inquirer/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/inquirer/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/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, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-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, + "license": "MIT", + "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-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "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-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "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==", + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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-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, + "license": "MIT", + "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.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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-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-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, + "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, + "license": "MIT", + "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-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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "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==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "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": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "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==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=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/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/lightningcss": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.25.1.tgz", + "integrity": "sha512-V0RMVZzK1+rCHpymRv4URK2lNhIRyO8g7U7zOFwVAhJuat74HtkjIQpQRKNCwFEYkRGpafOpmXXLoaoBcyVtBg==", + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.25.1", + "lightningcss-darwin-x64": "1.25.1", + "lightningcss-freebsd-x64": "1.25.1", + "lightningcss-linux-arm-gnueabihf": "1.25.1", + "lightningcss-linux-arm64-gnu": "1.25.1", + "lightningcss-linux-arm64-musl": "1.25.1", + "lightningcss-linux-x64-gnu": "1.25.1", + "lightningcss-linux-x64-musl": "1.25.1", + "lightningcss-win32-x64-msvc": "1.25.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.25.1.tgz", + "integrity": "sha512-G4Dcvv85bs5NLENcu/s1f7ehzE3D5ThnlWSDwE190tWXRQCQaqwcuHe+MGSVI/slm0XrxnaayXY+cNl3cSricw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.25.1.tgz", + "integrity": "sha512-dYWuCzzfqRueDSmto6YU5SoGHvZTMU1Em9xvhcdROpmtOQLorurUZz8+xFxZ51lCO2LnYbfdjZ/gCqWEkwixNg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.25.1.tgz", + "integrity": "sha512-hXoy2s9A3KVNAIoKz+Fp6bNeY+h9c3tkcx1J3+pS48CqAt+5bI/R/YY4hxGL57fWAIquRjGKW50arltD6iRt/w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.25.1.tgz", + "integrity": "sha512-tWyMgHFlHlp1e5iW3EpqvH5MvsgoN7ZkylBbG2R2LWxnvH3FuWCJOhtGcYx9Ks0Kv0eZOBud789odkYLhyf1ng==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.25.1.tgz", + "integrity": "sha512-Xjxsx286OT9/XSnVLIsFEDyDipqe4BcLeB4pXQ/FEA5+2uWCCuAEarUNQumRucnj7k6ftkAHUEph5r821KBccQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.25.1.tgz", + "integrity": "sha512-IhxVFJoTW8wq6yLvxdPvyHv4NjzcpN1B7gjxrY3uaykQNXPHNIpChLB52+wfH+yS58zm1PL4LemUp8u9Cfp6Bw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.25.1.tgz", + "integrity": "sha512-RXIaru79KrREPEd6WLXfKfIp4QzoppZvD3x7vuTKkDA64PwTzKJ2jaC43RZHRt8BmyIkRRlmywNhTRMbmkPYpA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.25.1.tgz", + "integrity": "sha512-TdcNqFsAENEEFr8fJWg0Y4fZ/nwuqTRsIr7W7t2wmDUlA8eSXVepeeONYcb+gtTj1RaXn/WgNLB45SFkz+XBZA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.25.1.tgz", + "integrity": "sha512-9KZZkmmy9oGDSrnyHuxP6iMhbsgChUiu/NSgOx+U1I/wTngBStDf2i2aGRCHvFqj19HqqBEI4WuGVQBa2V6e0A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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==" + }, + "node_modules/linkify-react": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/linkify-react/-/linkify-react-4.1.3.tgz", + "integrity": "sha512-rhI3zM/fxn5BfRPHfi4r9N7zgac4vOIxub1wHIWXLA5ENTMs+BGaIaFO1D1PhmxgwhIKmJz3H7uCP0Dg5JwSlA==", + "peerDependencies": { + "linkifyjs": "^4.0.0", + "react": ">= 15.0.0" + } + }, + "node_modules/linkifyjs": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.3.tgz", + "integrity": "sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==" + }, + "node_modules/lmdb": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.8.5.tgz", + "integrity": "sha512-9bMdFfc80S+vSldBmG3HOuLVHnxRdNTlpzR6QDnzqCQtCzGUEAGTzBKYMeIM+I/sU4oZfgbcbS7X7F65/z/oxQ==", + "hasInstallScript": true, + "dependencies": { + "msgpackr": "^1.9.5", + "node-addon-api": "^6.1.0", + "node-gyp-build-optional-packages": "5.1.1", + "ordered-binary": "^1.4.1", + "weak-lru-cache": "^1.2.2" + }, + "bin": { + "download-lmdb-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "2.8.5", + "@lmdb/lmdb-darwin-x64": "2.8.5", + "@lmdb/lmdb-linux-arm": "2.8.5", + "@lmdb/lmdb-linux-arm64": "2.8.5", + "@lmdb/lmdb-linux-x64": "2.8.5", + "@lmdb/lmdb-win32-x64": "2.8.5" + } + }, + "node_modules/lmdb/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, + "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==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "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==" + }, + "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/log-symbols/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/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/log-symbols/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/log-symbols/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/log-symbols/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/log-symbols/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/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/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "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.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "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/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/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/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/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mocksse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mocksse/-/mocksse-1.0.4.tgz", + "integrity": "sha512-W5DR/wwmx/EZUgjN1g+pvlhvFFtRJ3CqGRKqsK/B1hTxrjMb/t3JCbk6aomJD4WomrnueqMaTAhcAkIZJYd73w==", + "dev": true + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/msgpackr": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.2.tgz", + "integrity": "sha512-L60rsPynBvNE+8BWipKKZ9jHcSGbtyJYIwjRq0VrIvQ08cRjntGXJYW/tmciZ2IHWIY8WEW32Qa2xbh5+SKBZA==", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, + "node_modules/msgpackr-extract/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==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/msw": { + "version": "0.49.3", + "resolved": "https://registry.npmjs.org/msw/-/msw-0.49.3.tgz", + "integrity": "sha512-kRCbDNbNnRq5LC1H/NUceZlrPAvSrMH6Or0mirIuH69NY84xwDruPn/hkXTovIK1KwDwbk+ZdoSyJlpiekLxEA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@mswjs/cookies": "^0.2.2", + "@mswjs/interceptors": "^0.17.5", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^15.0.0 || ^16.0.0", + "headers-polyfill": "^3.1.0", + "inquirer": "^8.2.0", + "is-node-process": "^1.0.1", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.3.0", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.4.3", + "type-fest": "^2.19.0", + "yargs": "^17.3.1" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.4.x <= 4.9.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/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/msw/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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/msw/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/msw/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/msw/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/msw/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/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "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/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", + "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", + "engines": { + "node": "^16 || ^18 || >= 20" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", + "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==", + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/node-gyp-build-optional-packages/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "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, + "license": "MIT", + "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/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "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/ora/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/ora/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/ora/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/ora/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/ora/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/ora/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/ordered-binary": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.1.tgz", + "integrity": "sha512-5VyHfHY3cd0iza71JepYG50My+YUbrFtGoUz2ooEydPyPM7Aai/JW098juLr+RG6+rDJuzNNTsEQu2DZa1A41A==" + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/outvariant": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.2.tgz", + "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==", + "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, + "license": "MIT", + "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/parcel": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.12.0.tgz", + "integrity": "sha512-W+gxAq7aQ9dJIg/XLKGcRT0cvnStFAQHPaI0pvD0U2l6IVLueUAm3nwN7lkY62zZNmlvNx6jNtE4wlbS+CyqSg==", + "dependencies": { + "@parcel/config-default": "2.12.0", + "@parcel/core": "2.12.0", + "@parcel/diagnostic": "2.12.0", + "@parcel/events": "2.12.0", + "@parcel/fs": "2.12.0", + "@parcel/logger": "2.12.0", + "@parcel/package-manager": "2.12.0", + "@parcel/reporter-cli": "2.12.0", + "@parcel/reporter-dev-server": "2.12.0", + "@parcel/reporter-tracer": "2.12.0", + "@parcel/utils": "2.12.0", + "chalk": "^4.1.0", + "commander": "^7.0.0", + "get-port": "^4.2.0" + }, + "bin": { + "parcel": "lib/bin.js" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/parcel/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/parcel/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/parcel/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/parcel/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/parcel/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/parcel/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==" + }, + "node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "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/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==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "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.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/posthtml": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", + "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", + "dependencies": { + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/posthtml-parser": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", + "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dependencies": { + "is-json": "^2.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml/node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "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/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/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==" + }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "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-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "dependencies": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-cookie": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz", + "integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.0.1", + "hoist-non-react-statics": "^3.0.0", + "universal-cookie": "^4.0.0" + }, + "peerDependencies": { + "react": ">= 16.3.0" + } + }, + "node_modules/react-datepicker": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.25.0.tgz", + "integrity": "sha512-zB7CSi44SJ0sqo8hUQ3BF1saE/knn7u25qEMTO1CQGofY1VAKahO8k9drZtp0cfW1DMfoYLR3uSY1/uMvbEzbg==", + "dependencies": { + "@popperjs/core": "^2.11.8", + "classnames": "^2.2.6", + "date-fns": "^2.30.0", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0", + "react-popper": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" + } + }, + "node_modules/react-dnd": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", + "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", + "dependencies": { + "@react-dnd/invariant": "^4.0.1", + "@react-dnd/shallowequal": "^4.0.1", + "dnd-core": "^16.0.1", + "fast-deep-equal": "^3.1.3", + "hoist-non-react-statics": "^3.3.2" + }, + "peerDependencies": { + "@types/hoist-non-react-statics": ">= 3.3.1", + "@types/node": ">= 12", + "@types/react": ">= 16", + "react": ">= 16.14" + }, + "peerDependenciesMeta": { + "@types/hoist-non-react-statics": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-dnd-html5-backend": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", + "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", + "dependencies": { + "dnd-core": "^16.0.1" + } + }, + "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-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-hook-form": { + "version": "7.52.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.1.tgz", + "integrity": "sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-i18next": { + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", + "integrity": "sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==", + "dependencies": { + "@babel/runtime": "^7.20.6", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 19.0.0", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-icons": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", + "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-idle-timer": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/react-idle-timer/-/react-idle-timer-5.7.2.tgz", + "integrity": "sha512-+BaPfc7XEUU5JFkwZCx6fO1bLVK+RBlFH+iY4X34urvIzZiZINP6v2orePx3E6pAztJGE7t4DzvL7if2SL/0GQ==", + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-modal": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", + "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" + } + }, + "node_modules/react-onclickoutside": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.1.tgz", + "integrity": "sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" + }, + "peerDependencies": { + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + } + }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, + "node_modules/react-redux": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", + "integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==", + "dependencies": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^16.8 || ^17.0 || ^18.0", + "@types/react-dom": "^16.8 || ^17.0 || ^18.0", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0", + "react-native": ">=0.59", + "redux": "^4 || ^5.0.0-beta.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "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-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-router": { + "version": "6.23.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz", + "integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==", + "dependencies": { + "@remix-run/router": "1.16.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.23.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz", + "integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==", + "dependencies": { + "@remix-run/router": "1.16.1", + "react-router": "6.23.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-select": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.0.tgz", + "integrity": "sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-text-selection-popover": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/react-text-selection-popover/-/react-text-selection-popover-2.0.2.tgz", + "integrity": "sha512-VbQnJMHX6GrMRS5QGQnb8YuFL45JRcosraTJjdmjib4Xt9MOcTHXmuIyI12xbG2QZv2Tsa+aOZvYgTlo8I00dA==", + "dependencies": { + "use-text-selection": "^1.1.3" + }, + "peerDependencies": { + "react": "^16.8.0,^17.x,^18.x", + "react-dom": "^16.8.0,^17.x,^18.x" + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz", + "integrity": "sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "dependencies": { + "lodash": "^4.0.1" + } + }, + "node_modules/reactflow": { + "version": "11.11.3", + "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.11.3.tgz", + "integrity": "sha512-wusd1Xpn1wgsSEv7UIa4NNraCwH9syBtubBy4xVNXg3b+CDKM+sFaF3hnMx0tr0et4km9urIDdNvwm34QiZong==", + "dependencies": { + "@reactflow/background": "11.3.13", + "@reactflow/controls": "11.2.13", + "@reactflow/core": "11.11.3", + "@reactflow/minimap": "11.7.13", + "@reactflow/node-resizer": "2.2.13", + "@reactflow/node-toolbar": "1.3.13" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "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, + "license": "MIT", + "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/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexify-string": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/regexify-string/-/regexify-string-1.0.19.tgz", + "integrity": "sha512-EREOggl31J6v2Hk3ksPuOof0DMq5QhFfVQ7iDaGQ6BeA1QcrV4rhGvwCES5a72ITMmLBDAOb6cOWbn8/Ja82Ig==" + }, + "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, + "license": "MIT", + "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/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/remove-accents": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "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/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==", + "engines": { + "node": ">=4" + } + }, + "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/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/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true + }, + "node_modules/sass": { + "version": "1.77.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.5.tgz", + "integrity": "sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "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/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "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, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "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/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.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/strict-event-emitter": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.4.6.tgz", + "integrity": "sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "dev": true + }, + "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/string-width/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.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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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/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-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/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/timeago.js": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/timeago.js/-/timeago.js-4.0.2.tgz", + "integrity": "sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w==" + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==" + }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "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/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfck": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.0.tgz", + "integrity": "sha512-CMjc5zMnyAjcS9sPLytrbFmj89st2g+JYtY/c02ug4Q+CZaAtCgbyviI0n1YvjZE/pzoc6FbNsINS13DOL1B9w==", + "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": "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/tsconfig-paths/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/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/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": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "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, + "license": "MIT", + "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-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "dependencies": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + } + }, + "node_modules/universal-cookie/node_modules/@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" + }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "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.1.2", + "picocolors": "^1.0.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/use-callback-ref": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/use-text-selection": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/use-text-selection/-/use-text-selection-1.1.5.tgz", + "integrity": "sha512-JOuQYG0vKHRj0dfax0dy/HxyF31MN0Q2UP1rl1LtFA0qnQ0Uw4XGh4BucHA9g8kxlnVFv+JTlJQ4B+TwXCGxOg==", + "dependencies": { + "parcel": "^2.0.0-beta.2" + }, + "peerDependencies": { + "react": "^17.0.1" + } + }, + "node_modules/usehooks-ts": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.16.0.tgz", + "integrity": "sha512-bez95WqYujxp6hFdM/CpRDiVPirZPxlMzOH2QB8yopoKQMXpscyZoxOjpEdaxvV+CAWUDSM62cWnqHE0E/MZ7w==", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vite": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "dev": true, + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-env-compatible": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vite-plugin-env-compatible/-/vite-plugin-env-compatible-1.1.1.tgz", + "integrity": "sha512-4lqhBWhOzP+SaCPoCVdmpM5cXzjKQV5jgFauxea488oOeElXo/kw6bXkMIooZhrh9q7gclTl8en6N9NmnqUwRQ==", + "dev": true + }, + "node_modules/vite-plugin-svgr": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-2.4.0.tgz", + "integrity": "sha512-q+mJJol6ThvqkkJvvVFEndI4EaKIjSI0I3jNFgSoC9fXAz1M7kYTVUin8fhUsFojFDKZ9VHKtX6NXNaOLpbsHA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.2", + "@svgr/core": "^6.5.1" + }, + "peerDependencies": { + "vite": "^2.6.0 || 3 || 4" + } + }, + "node_modules/vite-plugin-transform": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vite-plugin-transform/-/vite-plugin-transform-2.0.1.tgz", + "integrity": "sha512-sI9SzcuFbCj04YHEmhw9C14kNnVq3QFLWq7eofjNnDWnw/p+i+6pnSvVZSx1GDVpW1ciZglrv794XEU/lGGvyA==", + "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.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "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/weak-lru-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", + "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==" + }, + "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==", + "dev": true, + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "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/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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "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": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "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/yup": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/zustand": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.2.tgz", + "integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/zustand/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + } + } +} diff --git a/GUI/package.json b/GUI/package.json new file mode 100644 index 0000000..09ab4a8 --- /dev/null +++ b/GUI/package.json @@ -0,0 +1,117 @@ +{ + "name": "byk-training-module-gui", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite --port 3001 --host", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "tsc --noEmit && eslint \"./src/**/*.{js,ts,tsx}\"", + "prettier": "prettier --write \"{,!(node_modules)/**/}*.{ts,tsx,js,json,css,less,scss}\"" + }, + "dependencies": { + "@buerokratt-ria/styles": "^0.0.1", + "@fontsource/roboto": "^4.5.8", + "@formkit/auto-animate": "^1.0.0-beta.5", + "@fortaine/fetch-event-source": "^3.0.6", + "@radix-ui/react-accessible-icon": "^1.0.1", + "@radix-ui/react-collapsible": "^1.0.1", + "@radix-ui/react-dialog": "^1.0.2", + "@radix-ui/react-popover": "^1.0.2", + "@radix-ui/react-progress": "^1.1.0", + "@radix-ui/react-select": "^1.1.2", + "@radix-ui/react-switch": "^1.0.1", + "@radix-ui/react-tabs": "^1.0.1", + "@radix-ui/react-toast": "^1.1.2", + "@radix-ui/react-tooltip": "^1.0.2", + "@tanstack/match-sorter-utils": "^8.7.2", + "@tanstack/react-query": "^4.36.1", + "@tanstack/react-table": "^8.7.4", + "axios": "^1.2.1", + "clsx": "^1.2.1", + "date-fns": "^2.29.3", + "downshift": "^7.0.5", + "esbuild": "^0.19.5", + "formik": "^2.4.6", + "framer-motion": "^8.5.5", + "howler": "^2.2.4", + "i18next": "^22.4.5", + "i18next-browser-languagedetector": "^7.0.1", + "linkify-react": "^4.1.1", + "linkifyjs": "^4.1.1", + "lodash": "^4.17.21", + "moment": "^2.30.1", + "react": "^18.2.0", + "react-color": "^2.19.3", + "react-cookie": "^4.1.1", + "react-datepicker": "^4.8.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", + "react-dom": "^18.2.0", + "react-hook-form": "^7.52.1", + "react-i18next": "^12.1.1", + "react-icons": "^4.10.1", + "react-idle-timer": "^5.5.2", + "react-modal": "^3.16.1", + "react-redux": "^8.1.1", + "react-router-dom": "^6.5.0", + "react-select": "^5.7.4", + "react-text-selection-popover": "^2.0.2", + "react-textarea-autosize": "^8.4.0", + "reactflow": "^11.4.0", + "regexify-string": "^1.0.19", + "rxjs": "^7.8.1", + "timeago.js": "^4.0.2", + "usehooks-ts": "^2.9.1", + "uuid": "^9.0.0", + "yup": "^1.4.0", + "zustand": "^4.4.4" + }, + "devDependencies": { + "@types/howler": "^2.2.11", + "@types/lodash": "^4.14.191", + "@types/lodash.debounce": "^4.0.7", + "@types/node": "^18.11.17", + "@types/react": "^18.0.26", + "@types/react-color": "^3.0.6", + "@types/react-datepicker": "^4.8.0", + "@types/react-dom": "^18.0.9", + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "^8.32.1", + "@typescript-eslint/parser": "^8.32.1", + "@vitejs/plugin-react": "^3.0.0", + "eslint": "^8.57.1", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.2", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-typescript": "^0.14.0", + "mocksse": "^1.0.4", + "msw": "^0.49.2", + "prettier": "^2.8.1", + "sass": "^1.57.0", + "typescript": "^4.9.3", + "vite": "^4.0.0", + "vite-plugin-env-compatible": "^1.1.1", + "vite-plugin-svgr": "^2.4.0", + "vite-plugin-transform": "^2.0.1", + "vite-tsconfig-paths": "^4.0.3" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "msw": { + "workerDirectory": "public" + } +} diff --git a/GUI/public/favicon.ico b/GUI/public/favicon.ico new file mode 100644 index 0000000..b9d127c Binary files /dev/null and b/GUI/public/favicon.ico differ diff --git a/GUI/public/mockServiceWorker.js b/GUI/public/mockServiceWorker.js new file mode 100644 index 0000000..671ec2c --- /dev/null +++ b/GUI/public/mockServiceWorker.js @@ -0,0 +1,303 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker (0.49.3). + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70' +const activeClientIds = new Set() + +self.addEventListener('install', function () { + self.skipWaiting() +}) + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()) +}) + +self.addEventListener('message', async function (event) { + const clientId = event.source.id + + if (!clientId || !self.clients) { + return + } + + const client = await self.clients.get(clientId) + + if (!client) { + return + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }) + break + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: INTEGRITY_CHECKSUM, + }) + break + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId) + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }) + break + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId) + break + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId) + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId + }) + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister() + } + + break + } + } +}) + +self.addEventListener('fetch', function (event) { + const { request } = event + const accept = request.headers.get('accept') || '' + + // Bypass server-sent events. + if (accept.includes('text/event-stream')) { + return + } + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return + } + + // Generate unique request ID. + const requestId = Math.random().toString(16).slice(2) + + event.respondWith( + handleRequest(event, requestId).catch((error) => { + if (error.name === 'NetworkError') { + console.warn( + '[MSW] Successfully emulated a network error for the "%s %s" request.', + request.method, + request.url, + ) + return + } + + // At this point, any exception indicates an issue with the original request/response. + console.error( + `\ +[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`, + request.method, + request.url, + `${error.name}: ${error.message}`, + ) + }), + ) +}) + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event) + const response = await getResponse(event, client, requestId) + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + ;(async function () { + const clonedResponse = response.clone() + sendToClient(client, { + type: 'RESPONSE', + payload: { + requestId, + type: clonedResponse.type, + ok: clonedResponse.ok, + status: clonedResponse.status, + statusText: clonedResponse.statusText, + body: + clonedResponse.body === null ? null : await clonedResponse.text(), + headers: Object.fromEntries(clonedResponse.headers.entries()), + redirected: clonedResponse.redirected, + }, + }) + })() + } + + return response +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId) + + if (client?.frameType === 'top-level') { + return client + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible' + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id) + }) +} + +async function getResponse(event, client, requestId) { + const { request } = event + const clonedRequest = request.clone() + + function passthrough() { + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const headers = Object.fromEntries(clonedRequest.headers.entries()) + + // Remove MSW-specific request headers so the bypassed requests + // comply with the server's CORS preflight check. + // Operate with the headers as an object because request "Headers" + // are immutable. + delete headers['x-msw-bypass'] + + return fetch(clonedRequest, { headers }) + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough() + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough() + } + + // Bypass requests with the explicit bypass header. + // Such requests can be issued by "ctx.fetch()". + if (request.headers.get('x-msw-bypass') === 'true') { + return passthrough() + } + + // Notify the client that a request has been intercepted. + const clientMessage = await sendToClient(client, { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + mode: request.mode, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: await request.text(), + bodyUsed: request.bodyUsed, + keepalive: request.keepalive, + }, + }) + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data) + } + + case 'MOCK_NOT_FOUND': { + return passthrough() + } + + case 'NETWORK_ERROR': { + const { name, message } = clientMessage.data + const networkError = new Error(message) + networkError.name = name + + // Rejecting a "respondWith" promise emulates a network error. + throw networkError + } + } + + return passthrough() +} + +function sendToClient(client, message) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error) + } + + resolve(event.data) + } + + client.postMessage(message, [channel.port2]) + }) +} + +function sleep(timeMs) { + return new Promise((resolve) => { + setTimeout(resolve, timeMs) + }) +} + +async function respondWithMock(response) { + await sleep(response.delay) + return new Response(response.body, response) +} diff --git a/GUI/rebuild.sh b/GUI/rebuild.sh new file mode 100644 index 0000000..c83c0b8 --- /dev/null +++ b/GUI/rebuild.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Install dependencies +apk add nodejs + +# Rebuild the project +cd /opt/buerokratt-classifier +./node_modules/.bin/vite build -l warn +cp -ru build/* /usr/share/nginx/html/buerokratt-classifier + +# Start the Nginx server +nginx -g "daemon off;" diff --git a/GUI/src/App.tsx b/GUI/src/App.tsx new file mode 100644 index 0000000..ceb8d83 --- /dev/null +++ b/GUI/src/App.tsx @@ -0,0 +1,76 @@ +import { FC, useEffect, useState } from 'react'; +import { Route, Routes, useNavigate, useLocation } from 'react-router-dom'; +import { Layout } from 'components'; +import useStore from 'store'; +import { useQuery } from '@tanstack/react-query'; +import { UserInfo } from 'types/userInfo'; +import { authQueryKeys } from 'utils/queryKeys'; +import { ROLES } from 'enums/roles'; +import LoadingScreen from 'pages/LoadingScreen/LoadingScreen'; +import LLMConnections from 'pages/LLMConnections'; +import CreateLLMConnection from 'pages/LLMConnections/CreateLLMConnection'; +import ViewLLMConnection from 'pages/LLMConnections/ViewLLMConnection'; +import UserManagement from 'pages/UserManagement'; +import TestLLM from 'pages/TestModel'; +import TestProductionLLM from 'pages/TestProductionLLM'; + +const App: FC = () => { + const navigate = useNavigate(); + const location = useLocation(); + const [hasRedirected, setHasRedirected] = useState(false); + const { isLoading, data } = useQuery({ + queryKey: authQueryKeys.USER_DETAILS(), + + onSuccess: (res: { response: UserInfo }) => { + localStorage.setItem('exp', res.response.JWTExpirationTimestamp); + useStore.getState().setUserInfo(res.response); + }, + }); + + useEffect(() => { + if (!isLoading && data && !hasRedirected && location.pathname === '/') { + const isAdmin = (data as { response: UserInfo }).response.authorities.some( + (item) => item === ROLES.ROLE_ADMINISTRATOR + ); + if (isAdmin) { + navigate('/user-management'); + } else { + navigate('/dataset-groups'); + } + setHasRedirected(true); + } + }, [isLoading, data, navigate, hasRedirected, location.pathname]); + + return ( + <> + {isLoading ? ( + + ) : ( + + }> + {(data as { response: UserInfo })?.response.authorities.some( + (item) => item === ROLES.ROLE_ADMINISTRATOR + ) ? ( + <> + } /> + + ) : ( + <> + // unauthorized route + + )} + } /> + } /> + } /> + } /> + } /> + + + + + )} + + ); +}; + +export default App; diff --git a/GUI/src/assets/BackArrowButton.tsx b/GUI/src/assets/BackArrowButton.tsx new file mode 100644 index 0000000..e8e60eb --- /dev/null +++ b/GUI/src/assets/BackArrowButton.tsx @@ -0,0 +1,31 @@ +const BackArrowButton = () => { + return ( + + + + + + + + + + + + ); +}; + +export default BackArrowButton; diff --git a/GUI/src/assets/DataModelsIcon.tsx b/GUI/src/assets/DataModelsIcon.tsx new file mode 100644 index 0000000..855dd73 --- /dev/null +++ b/GUI/src/assets/DataModelsIcon.tsx @@ -0,0 +1,20 @@ +import React from 'react'; + +const DataModelsIcon = () => { + return ( + + + + ); +}; + +export default DataModelsIcon; diff --git a/GUI/src/assets/DatabaseIcon.tsx b/GUI/src/assets/DatabaseIcon.tsx new file mode 100644 index 0000000..5ab9d3b --- /dev/null +++ b/GUI/src/assets/DatabaseIcon.tsx @@ -0,0 +1,37 @@ +import React from 'react'; + +const DatabaseIcon = () => { + return ( + + + + + + ); +}; + +export default DatabaseIcon; diff --git a/GUI/src/assets/Dataset.tsx b/GUI/src/assets/Dataset.tsx new file mode 100644 index 0000000..6b46aff --- /dev/null +++ b/GUI/src/assets/Dataset.tsx @@ -0,0 +1,18 @@ +const Dataset = () => { + return ( + + + + ); +}; + +export default Dataset; diff --git a/GUI/src/assets/IncomingTextsIcon.tsx b/GUI/src/assets/IncomingTextsIcon.tsx new file mode 100644 index 0000000..fb6ccb9 --- /dev/null +++ b/GUI/src/assets/IncomingTextsIcon.tsx @@ -0,0 +1,20 @@ +import React from 'react'; + +const IncomingTextsIcon = () => { + return ( + + + + ); +}; + +export default IncomingTextsIcon; diff --git a/GUI/src/assets/IntegrationIcon.tsx b/GUI/src/assets/IntegrationIcon.tsx new file mode 100644 index 0000000..5553ea5 --- /dev/null +++ b/GUI/src/assets/IntegrationIcon.tsx @@ -0,0 +1,42 @@ +import React from 'react'; + +const IntegrationIcon = () => { + return ( + + + + + + + + + + + + ); +}; + +export default IntegrationIcon; diff --git a/GUI/src/assets/Jira.tsx b/GUI/src/assets/Jira.tsx new file mode 100644 index 0000000..3708879 --- /dev/null +++ b/GUI/src/assets/Jira.tsx @@ -0,0 +1,55 @@ +const Jira = () => { + return ( + + + + + + + + + + + + + + + + + + + + + + ); +}; +export default Jira; diff --git a/GUI/src/assets/Outlook.tsx b/GUI/src/assets/Outlook.tsx new file mode 100644 index 0000000..5eb0ebb --- /dev/null +++ b/GUI/src/assets/Outlook.tsx @@ -0,0 +1,25 @@ +const Outlook = () => { + return ( + + + + + + ); +}; +export default Outlook; diff --git a/GUI/src/assets/SearchIcon.tsx b/GUI/src/assets/SearchIcon.tsx new file mode 100644 index 0000000..60e6676 --- /dev/null +++ b/GUI/src/assets/SearchIcon.tsx @@ -0,0 +1,20 @@ +import React from 'react'; + +const SearchIcon = () => { + return ( + + + + ); +}; + +export default SearchIcon; diff --git a/GUI/src/assets/TestModelIcon.tsx b/GUI/src/assets/TestModelIcon.tsx new file mode 100644 index 0000000..6b9c45f --- /dev/null +++ b/GUI/src/assets/TestModelIcon.tsx @@ -0,0 +1,32 @@ +import React from 'react'; + +const TestModelIcon = () => { + return ( + + + + + + + + + + + ); +}; + +export default TestModelIcon; diff --git a/GUI/src/assets/UserIcon.tsx b/GUI/src/assets/UserIcon.tsx new file mode 100644 index 0000000..83c84c0 --- /dev/null +++ b/GUI/src/assets/UserIcon.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +const UserIcon = () => { + return ( + + + + + ); +}; + +export default UserIcon; diff --git a/GUI/src/assets/logo-white.svg b/GUI/src/assets/logo-white.svg new file mode 100644 index 0000000..2025736 --- /dev/null +++ b/GUI/src/assets/logo-white.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + diff --git a/GUI/src/assets/logo.svg b/GUI/src/assets/logo.svg new file mode 100644 index 0000000..6039e9b --- /dev/null +++ b/GUI/src/assets/logo.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/GUI/src/assets/newMessageSound.mp3 b/GUI/src/assets/newMessageSound.mp3 new file mode 100644 index 0000000..9400b22 Binary files /dev/null and b/GUI/src/assets/newMessageSound.mp3 differ diff --git a/GUI/src/components/Box/Box.scss b/GUI/src/components/Box/Box.scss new file mode 100644 index 0000000..8801c05 --- /dev/null +++ b/GUI/src/components/Box/Box.scss @@ -0,0 +1,56 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.box { + padding: get-spacing(paldiski); + border-radius: 4px; + border: 1px solid; + font-size: $veera-font-size-100; + line-height: $veera-line-height-500; + + &:hover { + cursor: grab; + } + + &--default { + background-color: get-color(black-coral-1); + border-color: get-color(black-coral-3); + } + + &--blue { + background-color: get-color(sapphire-blue-0); + border-color: get-color(sapphire-blue-2); + } + + &--yellow { + background-color: get-color(dark-tangerine-0); + border-color: get-color(dark-tangerine-4); + } + + &--green { + background-color: get-color(sea-green-1); + border-color: get-color(sea-green-3); + } + + &--red { + background-color: get-color(jasper-1); + border-color: get-color(jasper-3); + } + + &--gray { + background-color: get-color(black-coral-1); + border-color: get-color(black-coral-3); + } + + &--dark-blue { + background-color: get-color(sapphire-blue-3); + border-color: get-color(sapphire-blue-5); + } + + &--orange { + background-color: get-color(orange-3); + border-color: get-color(orange-5); + } +} diff --git a/GUI/src/components/Box/index.tsx b/GUI/src/components/Box/index.tsx new file mode 100644 index 0000000..df4d399 --- /dev/null +++ b/GUI/src/components/Box/index.tsx @@ -0,0 +1,16 @@ +import { forwardRef, PropsWithChildren } from 'react'; +import clsx from 'clsx'; + +import './Box.scss'; + +type BoxProps = { + color?: 'default' | 'blue' | 'yellow' | 'green' | 'red' | 'gray' | 'dark-blue' | 'orange'; +} + +const Box = forwardRef>(({ color = 'default', children }, ref) => { + return ( +
{children}
+ ); +}); + +export default Box; diff --git a/GUI/src/components/Button/Button.scss b/GUI/src/components/Button/Button.scss new file mode 100644 index 0000000..217c2c0 --- /dev/null +++ b/GUI/src/components/Button/Button.scss @@ -0,0 +1,151 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.btn { + $self: &; + appearance: none; + display: inline-flex; + align-items: center; + background: none; + border: 0; + color: get-color(black-coral-0); + cursor: pointer; + font: inherit; + gap: get-spacing(rapla); + overflow: visible; + padding: 8px 40px; + text-decoration: none; + font-size: $veera-font-size-100; + line-height: 24px; + border-radius: 20px; + white-space: nowrap; + height: fit-content; + + &:focus { + outline: none; + } + + &--disabled { + cursor: not-allowed; + } + + &--primary { + background-color: get-color(sapphire-blue-10); + + &:hover, + &:active { + background-color: get-color(sapphire-blue-13); + } + + &:focus { + box-shadow: inset 0 0 0 2px get-color(sapphire-blue-3) + } + + &#{$self}--disabled { + background-color: get-color(black-coral-2); + color: get-color(white); + } + } + + &--secondary { + background-color: get-color(white); + box-shadow: inset 0 0 0 2px get-color(sapphire-blue-10); + color: get-color(sapphire-blue-10); + + &:hover, + &:active { + box-shadow: inset 0 0 0 2px get-color(black-coral-2); + } + + &:focus { + box-shadow: inset 0 0 0 2px get-color(sapphire-blue-10); + } + + &#{$self}--disabled { + background-color: get-color(black-coral-2); + color: get-color(black-coral-6); + box-shadow: inset 0 0 0 2px get-color(black-coral-2); + } + } + + &--text { + padding: 0; + background: none; + color: get-color(sapphire-blue-10); + gap: 4px; + border-radius: 0; + + &:hover, + &:active { + text-decoration: underline; + } + + &:focus { + box-shadow: inset 0 0 0 2px get-color(sapphire-blue-10); + } + + &#{$self}--disabled { + color: get-color(black-coral-6); + } + } + + &--icon { + width: 36px; + height: 36px; + padding: 0; + justify-content: center; + color: get-color(black-coral-10); + font-size: 24px; + + &:hover, + &:active { + color: get-color(sapphire-blue-10); + } + + &:focus { + color: get-color(sapphire-blue-10); + box-shadow: inset 0 0 0 2px get-color(sapphire-blue-10); + } + } + + &--error { + background-color: get-color(jasper-10); + + &:hover, + &:active { + background-color: get-color(jasper-12); + } + + &:focus { + box-shadow: inset 0 0 0 2px get-color(jasper-13); + } + + &#{$self}--disabled { + background-color: get-color(black-coral-2); + } + } + + &--success { + background-color: get-color(sea-green-10); + + &:hover, + &:active { + background-color: get-color(sea-green-12); + } + + &:focus { + background-color: get-color(sea-green-10); + box-shadow: inset 0 0 0 2px get-color(sea-green-12); + } + + &#{$self}--disabled { + background-color: get-color(black-coral-2); + } + } + + &--s { + padding: 4.5px 24px; + } +} diff --git a/GUI/src/components/Button/index.tsx b/GUI/src/components/Button/index.tsx new file mode 100644 index 0000000..b35cd8c --- /dev/null +++ b/GUI/src/components/Button/index.tsx @@ -0,0 +1,56 @@ +import { ButtonHTMLAttributes, FC, PropsWithChildren, useRef } from 'react'; +import clsx from 'clsx'; + +import './Button.scss'; + +type ButtonProps = ButtonHTMLAttributes & { + appearance?: 'primary' | 'secondary' | 'text' | 'icon' | 'error' | 'success'; + size?: 'm' | 's'; + disabledWithoutStyle?: boolean; + showLoadingIcon?: boolean; +}; + +const Button: FC> = ({ + appearance = 'primary', + size = 'm', + disabled, + disabledWithoutStyle = false, + children, + showLoadingIcon = false, + ...rest +}) => { + const ref = useRef(null); + + const buttonClasses = clsx( + 'btn', + `btn--${appearance}`, + `btn--${size}`, + disabled && 'btn--disabled' + ); + + return ( + + ); +}; + +export default Button; \ No newline at end of file diff --git a/GUI/src/components/Card/Card.scss b/GUI/src/components/Card/Card.scss new file mode 100644 index 0000000..82d2665 --- /dev/null +++ b/GUI/src/components/Card/Card.scss @@ -0,0 +1,65 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.card { + $self: &; + background-color: get-color(white); + border: 1px solid get-color(black-coral-2); + border-radius: $veera-radius-s; + margin-bottom: 10px; + + &--borderless { + border: 0; + border-radius: 0; + + #{$self}__header { + border-radius: 0; + } + } + + &--fullWidth { + width: 100%; + } + + &__header, + &__body, + &__footer { + padding: get-spacing(haapsalu); + } + + &__header { + border-bottom: 1px solid get-color(black-coral-2); + background-color: #F9F9F9; + border-radius: $veera-radius-s $veera-radius-s 0 0; + + &.white { + background-color: white + } + } + + &__body { + &.divided { + display: flex; + flex-direction: column; + padding-left: 0px; + padding-right: 0px; + + > :not(:last-child) { + margin-bottom: get-spacing(haapsalu); + border-bottom: 1px solid get-color(black-coral-2); + padding-bottom: get-spacing(haapsalu); + padding-left: get-spacing(haapsalu); + } + + > :is(:last-child) { + padding-left: get-spacing(haapsalu); + } + } + } + + &__footer { + border-top: 1px solid get-color(black-coral-2); + } +} diff --git a/GUI/src/components/Card/index.tsx b/GUI/src/components/Card/index.tsx new file mode 100644 index 0000000..27eb750 --- /dev/null +++ b/GUI/src/components/Card/index.tsx @@ -0,0 +1,39 @@ +import { FC, PropsWithChildren, ReactNode } from 'react'; +import clsx from 'clsx'; + +import './Card.scss'; + +type CardProps = { + header?: ReactNode; + footer?: ReactNode; + borderless?: boolean; + isHeaderLight?: boolean; + isBodyDivided?: boolean; + isFullWidth?: boolean; +}; + +const Card: FC> = ({ + header, + footer, + borderless, + isHeaderLight, + isBodyDivided, + children, + isFullWidth, +}) => { + return ( +
+ {header && ( +
+ {header} +
+ )} +
+ {children} +
+ {footer &&
{footer}
} +
+ ); +}; + +export default Card; diff --git a/GUI/src/components/Collapsible/Collapsible.scss b/GUI/src/components/Collapsible/Collapsible.scss new file mode 100644 index 0000000..24328e6 --- /dev/null +++ b/GUI/src/components/Collapsible/Collapsible.scss @@ -0,0 +1,35 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.collapsible { + border: 1px solid get-color(black-coral-2); + border-radius: 4px; + + &__trigger { + width: 100%; + display: flex; + align-items: center; + gap: 4px; + padding: get-spacing(haapsalu); + background-color: get-color(extra-light); + border-radius: 4px; + + &[aria-expanded=true] { + border-bottom: 1px solid get-color(black-coral-2); + border-radius: 4px 4px 0 0; + } + + .icon { + font-size: 21px; + } + } + + &__content { + padding: get-spacing(haapsalu); + background-color: get-color(white); + border-radius: 0 0 4px 4px; + overflow: hidden; + } +} diff --git a/GUI/src/components/Collapsible/index.tsx b/GUI/src/components/Collapsible/index.tsx new file mode 100644 index 0000000..02a13bd --- /dev/null +++ b/GUI/src/components/Collapsible/index.tsx @@ -0,0 +1,31 @@ +import { FC, PropsWithChildren, useState } from 'react'; +import * as RadixCollapsible from '@radix-ui/react-collapsible'; +import { MdOutlineAddBox, MdOutlineIndeterminateCheckBox } from 'react-icons/md'; + +import { Icon } from 'components'; +import './Collapsible.scss'; + +type CollapsibleProps = { + title: string; + defaultOpen?: boolean; +} + +const Collapsible: FC> = ({ defaultOpen = false, title, children }) => { + const [open, setOpen] = useState(defaultOpen); + + return ( + + + + + + {children} + + + ); +}; + +export default Collapsible; diff --git a/GUI/src/components/DataTable/CloseIcon.tsx b/GUI/src/components/DataTable/CloseIcon.tsx new file mode 100644 index 0000000..85de2db --- /dev/null +++ b/GUI/src/components/DataTable/CloseIcon.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import './DeboucedInput.scss'; + +const CloseIcon: React.FC = () => ( + + + + +); + +export default CloseIcon; diff --git a/GUI/src/components/DataTable/DataTable.scss b/GUI/src/components/DataTable/DataTable.scss new file mode 100644 index 0000000..50dd75d --- /dev/null +++ b/GUI/src/components/DataTable/DataTable.scss @@ -0,0 +1,266 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/typography'; + +.data-table { + width: 100%; + color: get-color(black-coral-20); + text-align: left; + margin-bottom: 0; + display: table; + + &__scrollWrapper { + height: 100%; + min-height: 150px !important; + padding: 10px 20px; + overflow-x: auto; + white-space: nowrap; + display: block; + background-color: white; + border-radius: 10px; + border: solid 1px get-color(black-coral-1); + } + + &__page-size-selector { + display: flex; + gap: .7rem; + } + + thead, + tbody { + width: 100%; + } + + th { + padding: 12px 14.5px; + color: get-color(black-coral-12); + border-bottom: 1px solid get-color(black-coral-10); + font-weight: $veera-font-weight-beta; + vertical-align: middle; + position: relative; + } + + td { + padding: 12px 24px 12px 16px; + border-bottom: 1px solid get-color(black-coral-2); + vertical-align: middle; + max-width: fit-content; + + p { + white-space: break-spaces; + } + + .entity { + display: inline-flex; + align-items: center; + padding-left: 4px; + background-color: get-color(sapphire-blue-2); + border-radius: 4px; + + span { + display: inline-flex; + font-size: $veera-font-size-80; + background-color: get-color(white); + padding: 0 4px; + border-radius: 4px; + margin: 2px 2px 2px 4px; + } + } + } + + tbody { + tr { + &:last-child { + td { + border-bottom: 0; + } + } + } + } + + &__filter { + position: absolute; + top: 100%; + left: 0; + right: 0; + padding: get-spacing(paldiski); + background-color: get-color(white); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.14); + border-radius: 0 0 4px 4px; + border: 1px solid get-color(black-coral-2); + + input { + width: 100%; + display: block; + appearance: none; + background-color: get-color(white); + border: 1px solid get-color(black-coral-6); + border-radius: 5px; + color: var(--color-black); + font-size: $veera-font-size-100; + height: 32px; + line-height: 24px; + padding: get-spacing(paldiski); + + &::placeholder { + color: get-color(black-coral-6); + } + + &:focus { + outline: none; + border-color: get-color(sapphire-blue-10); + } + } + } + + &__dropdown_filter { + position: absolute; + top: 100%; + left: 0; + padding: get-spacing(paldiski); + background-color: get-color(white); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.14); + border-radius: 0 0 4px 4px; + border: 1px solid get-color(black-coral-2); + width: "fit-content"; + } + + &__pagination-wrapper { + margin-top: 10px; + display: flex; + padding: 6px 16px; + } + + &__pagination { + display: flex; + align-items: center; + gap: 15px; + margin: 0 auto; + + + .data-table__page-size { + margin-left: 0; + } + + .next, + .previous { + display: flex; + color: get-color(sapphire-blue-10); + + &[disabled] { + color: get-color(black-coral-11); + cursor: initial; + } + } + + .links { + display: flex; + align-items: center; + gap: 5px; + font-size: $veera-font-size-80; + color: get-color(black-coral-10); + + li { + display: block; + + a, + span { + display: flex; + align-items: center; + justify-content: center; + width: 25px; + height: 25px; + border-radius: 50%; + + &:hover { + text-decoration: none; + } + } + + &.active { + a, + span { + color: get-color(white); + background-color: get-color(sapphire-blue-10); + } + } + } + } + } + + &__page-size { + display: flex; + align-items: center; + gap: 8px; + font-size: $veera-font-size-80; + line-height: 16px; + color: get-color(black-coral-11); + margin-left: auto; + + select { + appearance: none; + font-size: $veera-font-size-70; + line-height: 16px; + height: 30px; + min-width: 50px; + padding: 6px 10px; + border: 1px solid #8f91a8; + border-radius: 2px; + background-color: get-color(white); + background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNiIgdmlld0JveD0iMCAwIDEwIDYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNS4zMTMwNiA1LjgwODIyQzUuMTU2ODUgNS45NjQ0MyA0LjkwMzU4IDUuOTY0NDMgNC43NDczNyA1LjgwODIyTDAuMjgyNzMgMS4zNDM1OEMwLjEyNjUyIDEuMTg3MzcgMC4xMjY1MiAwLjkzNDEwMiAwLjI4MjczIDAuNzc3ODkzTDAuNzc3NzA0IDAuMjgyOTE4QzAuOTMzOTE0IDAuMTI2NzA4IDEuMTg3MTggMC4xMjY3MDggMS4zNDMzOSAwLjI4MjkxN0w1LjAzMDIyIDMuOTY5NzRMOC43MTcwNCAwLjI4MjkxN0M4Ljg3MzI1IDAuMTI2NzA4IDkuMTI2NTIgMC4xMjY3MDggOS4yODI3MyAwLjI4MjkxN0w5Ljc3NzcgMC43Nzc4OTJDOS45MzM5MSAwLjkzNDEwMiA5LjkzMzkxIDEuMTg3MzcgOS43Nzc3IDEuMzQzNThMNS4zMTMwNiA1LjgwODIyWiIgZmlsbD0iIzU1NTg2NyIvPgo8L3N2Zz4K'); + background-repeat: no-repeat; + background-position: top 11px right 10px; + } + } +} + +.dataset-controls { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; + padding: 0 1rem; + flex-wrap: wrap; + gap: 1rem; + + .filter-controls { + display: flex; + gap: 0.5rem; + align-items: center; + } + + .bulk-actions { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.5rem 1rem; + background-color: get-color(jasper-0); + border: 1px solid get-color(jasper-10); + border-radius: 6px; + + .selected-count { + font-size: 0.875rem; + color: get-color(jasper-10); + font-weight: 500; + } + } +} + +.data-table { + input[type="checkbox"] { + width: 16px; + height: 16px; + cursor: pointer; + accent-color: get-color(sapphire-blue-10); + } +} + +@media (max-width: 768px) { + .dataset-controls { + flex-direction: column; + align-items: stretch; + + .bulk-actions { + justify-content: center; + } + } +} \ No newline at end of file diff --git a/GUI/src/components/DataTable/DeboucedInput.scss b/GUI/src/components/DataTable/DeboucedInput.scss new file mode 100644 index 0000000..753f1ad --- /dev/null +++ b/GUI/src/components/DataTable/DeboucedInput.scss @@ -0,0 +1,11 @@ +.input-container { + position: relative; +} + +.search-icon { + position: absolute; + top: 50%; + right: 10px; + margin-left: 10px; + transform: translateY(-50%); +} diff --git a/GUI/src/components/DataTable/DebouncedInput.tsx b/GUI/src/components/DataTable/DebouncedInput.tsx new file mode 100644 index 0000000..1ad1f52 --- /dev/null +++ b/GUI/src/components/DataTable/DebouncedInput.tsx @@ -0,0 +1,54 @@ +import { FC, InputHTMLAttributes, useEffect, useState } from 'react'; +import './DeboucedInput.scss'; +import CloseIcon from './CloseIcon'; + +type DebouncedInputProps = Omit< + InputHTMLAttributes, + 'onChange' +> & { + value: string | number | string[]; + onChange: (value: string | number | string[]) => void; + debounce?: number; +}; + +const DebouncedInput: FC = ({ + value: initialValue, + onChange, + debounce = 500, + ...props +}) => { + const [value, setValue] = useState(initialValue); + + useEffect(() => { + setValue(initialValue); + }, [initialValue]); + + useEffect(() => { + const timeout = setTimeout(() => { + onChange(value); + }, debounce); + + return () => clearTimeout(timeout); + }, [value]); + + return ( +
+ setValue(e.target.value)} + /> + {value && ( + + )} +
+ ); +}; + +export default DebouncedInput; diff --git a/GUI/src/components/DataTable/DropdownFilter.tsx b/GUI/src/components/DataTable/DropdownFilter.tsx new file mode 100644 index 0000000..4009590 --- /dev/null +++ b/GUI/src/components/DataTable/DropdownFilter.tsx @@ -0,0 +1,55 @@ +import React, { FC, useState, MouseEvent } from 'react'; +import { Column, Table } from '@tanstack/react-table'; +import { useTranslation } from 'react-i18next'; +import { MdOutlineFilterList } from 'react-icons/md'; + +import { Icon } from 'components'; +import useDocumentEscapeListener from 'hooks/useDocumentEscapeListener'; + +type DropdownFilterProps = { + column: Column; + table: Table; + options: { label: string; value: string | number }[]; + onSelect: (value: string | number) => void; // <-- Add this prop +}; + +const DropdownFilter: FC = ({ column, table, options, onSelect }) => { + const { t } = useTranslation(); + const [filterOpen, setFilterOpen] = useState(false); + const [selectedValue, setSelectedValue] = useState(''); + + useDocumentEscapeListener(() => setFilterOpen(false)); + + const handleFilterToggle = (e: MouseEvent) => { + e.stopPropagation(); + setFilterOpen(!filterOpen); + }; + + const handleSelect = (e: React.ChangeEvent) => { + setSelectedValue(e.target.value); + setFilterOpen(false); + onSelect(e.target.value); // <-- Call the callback with the selected value + }; + + return ( + <> + + {filterOpen && ( +
+ +
+ )} + + ); +}; + +export default DropdownFilter; \ No newline at end of file diff --git a/GUI/src/components/DataTable/Filter.tsx b/GUI/src/components/DataTable/Filter.tsx new file mode 100644 index 0000000..038d811 --- /dev/null +++ b/GUI/src/components/DataTable/Filter.tsx @@ -0,0 +1,65 @@ +import React, { FC, useState, MouseEvent } from 'react'; +import { Column, Table } from '@tanstack/react-table'; +import { useTranslation } from 'react-i18next'; +import { MdOutlineSearch } from 'react-icons/md'; + +import { Icon } from 'components'; +import useDocumentEscapeListener from 'hooks/useDocumentEscapeListener'; +import DebouncedInput from './DebouncedInput'; + +type FilterProps = { + column: Column; + table: Table; +}; + +const Filter: FC = ({ column, table }) => { + const { t } = useTranslation(); + const [filterOpen, setFilterOpen] = useState(false); + const firstValue = table + .getPreFilteredRowModel() + .flatRows[0]?.getValue(column.id); + + const columnFilterValue = column.getFilterValue(); + + useDocumentEscapeListener(() => setFilterOpen(false)); + + const handleFilterToggle = (e: MouseEvent) => { + e.stopPropagation(); + setFilterOpen(!filterOpen); + }; + + return ( + <> + + {filterOpen && ( +
+ {typeof firstValue === 'number' ? ( + + column.setFilterValue((old: [number, number]) => [ + value, + old?.[1], + ]) + } + /> + ) : ( + column.setFilterValue(value)} + placeholder={t('global.search') + '...'} + /> + )} +
+ )} + + ); +}; + +export default Filter; diff --git a/GUI/src/components/DataTable/index.tsx b/GUI/src/components/DataTable/index.tsx new file mode 100644 index 0000000..1693489 --- /dev/null +++ b/GUI/src/components/DataTable/index.tsx @@ -0,0 +1,332 @@ +import React, { CSSProperties, FC, ReactNode, useId } from 'react'; +import { + ColumnDef, + useReactTable, + getCoreRowModel, + flexRender, + getSortedRowModel, + SortingState, + FilterFn, + getFilteredRowModel, + VisibilityState, + getPaginationRowModel, + PaginationState, + TableMeta, + Row, + RowData, ColumnFiltersState, RowSelectionState, + +} from '@tanstack/react-table'; +import { + RankingInfo, + rankItem, +} from '@tanstack/match-sorter-utils'; +import { + MdUnfoldMore, + MdExpandMore, + MdExpandLess, + MdOutlineEast, + MdOutlineWest, +} from 'react-icons/md'; +import clsx from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { Icon, Track } from 'components'; +import Filter from './Filter'; +import './DataTable.scss'; +import DropdownFilter from './DropdownFilter'; +import NoDataView from 'components/molecules/NoDataView'; + +type DataTableProps = { + data: any; + columns: ColumnDef[]; + tableBodyPrefix?: ReactNode; + isClientSide?: boolean; + sortable?: boolean; + filterable?: boolean; + pagination?: PaginationState; + sorting?: SortingState; + setPagination?: (state: PaginationState) => void; + setSorting?: (state: SortingState) => void; + globalFilter?: string; + setGlobalFilter?: React.Dispatch>; + columnVisibility?: VisibilityState; + setColumnVisibility?: React.Dispatch>; + disableHead?: boolean; + pagesCount?: number; + meta?: TableMeta; + dropdownFilters?: DropdownFilterConfig[]; + onSelect?: (value: string | number) => void | undefined + showPageSizeSelector?: boolean; + pageSizeOptions?: number[]; + rowSelection?: RowSelectionState; + setRowSelection?: (state: RowSelectionState) => void; +}; + +type ColumnMeta = { + meta: { + size: number | string; + } +} + +type CustomColumnDef = ColumnDef & ColumnMeta; + +type DropdownFilterConfig = { + columnId: string; + options: { label: string; value: string | number }[]; +}; + +declare module '@tanstack/table-core' { + interface FilterFns { + fuzzy: FilterFn; + } + + interface FilterMeta { + itemRank: RankingInfo; + } +} + +declare module '@tanstack/react-table' { + interface TableMeta { + getRowStyles: (row: Row) => CSSProperties; + } + class Column { + columnDef: CustomColumnDef; + } +} + +const fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => { + const itemRank = rankItem(row.getValue(columnId), value); + addMeta({ + itemRank, + }); + return itemRank.passed; +}; + +const DataTable: FC = ( + { + data, + columns, + isClientSide = true, + tableBodyPrefix, + sortable, + filterable, + pagination, + sorting, + setPagination, + setSorting, + globalFilter, + setGlobalFilter, + columnVisibility, + setColumnVisibility, + disableHead, + pagesCount, + meta, + dropdownFilters, + onSelect, + showPageSizeSelector = false, + pageSizeOptions = [10, 20, 50, 100], + rowSelection, + setRowSelection, + }, +) => { + const id = useId(); + const { t } = useTranslation(); + const [columnFilters, setColumnFilters] = React.useState([]); + const table = useReactTable({ + data, + columns, + filterFns: { + fuzzy: fuzzyFilter, + }, + state: { + sorting, + columnFilters, + globalFilter, + columnVisibility, + ...{ pagination }, + ...(rowSelection && { rowSelection }), + }, + meta, + onColumnFiltersChange: setColumnFilters, + onGlobalFilterChange: setGlobalFilter, + onColumnVisibilityChange: setColumnVisibility, + globalFilterFn: fuzzyFilter, + enableRowSelection: !!setRowSelection, + onRowSelectionChange: setRowSelection + ? (updaterOrValue) => { + if (typeof updaterOrValue === 'function') { + setRowSelection(updaterOrValue(table.getState().rowSelection)); + } else { + setRowSelection(updaterOrValue); + } + } + : undefined, + onSortingChange: (updater) => { + if (typeof updater !== 'function') return; + setSorting?.(updater(table.getState().sorting)); + }, + onPaginationChange: (updater) => { + if (typeof updater !== 'function') return; + setPagination?.(updater(table.getState().pagination)); + }, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + ...(pagination && { getPaginationRowModel: getPaginationRowModel() }), + ...(sortable && { getSortedRowModel: getSortedRowModel() }), + manualPagination: isClientSide ? undefined : true, + manualSorting: isClientSide ? undefined : true, + pageCount: isClientSide ? undefined : pagesCount, + }); + + const handlePageSizeChange = (newPageSize: number) => { + if (setPagination && pagination) { + setPagination({ + pageIndex: 0, + pageSize: newPageSize, + }); + } + }; + + return ( +
+ + {!disableHead && ( + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + ))} + + ))} + + )} + + {!data || data.length === 0 ? ( + + + + ) : ( + <> + {tableBodyPrefix} + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + ))} + + ))} + + ) + + } + + +
+ {header.isPlaceholder ? null : ( + + {sortable && header.column.getCanSort() && ( + + )} + {flexRender(header.column.columnDef.header, header.getContext())} + {dropdownFilters && header.column.getCanFilter() && ( + (() => { + const dropdownConfig = dropdownFilters?.find( + (df) => df.columnId === header.column.id + ); + + if (dropdownConfig) { + return ( + { })} + /> + ); + } + + })() + )} + {filterable && header.column.getCanFilter() && ( + )} + + )} +
+ +
{flexRender(cell.column.columnDef.cell, cell.getContext())}
+ {pagination && ( +
+ {showPageSizeSelector && ( +
+ + {t('global.showEntries') || 'Show'} + + + + {t('global.entries') || 'entries'} + +
+ )} + {(table.getPageCount() * table.getState().pagination.pageSize) > table.getState().pagination.pageSize && ( +
+ + + +
+ )} +
+ )} +
+ ); +}; + +export default DataTable; \ No newline at end of file diff --git a/GUI/src/components/Dialog/Dialog.scss b/GUI/src/components/Dialog/Dialog.scss new file mode 100644 index 0000000..bc67c6e --- /dev/null +++ b/GUI/src/components/Dialog/Dialog.scss @@ -0,0 +1,63 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.dialog { + background-color: get-color(white); + box-shadow: 0 0 20px rgba(0, 0, 0, 0.25); + border-radius: 4px; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + max-width: 600px; + z-index: 1011111; + max-height: 90vh; + + &--large { + max-width: 800px; + } + + &__overlay { + position: fixed; + inset: 0; + background-color: rgba(0, 0, 0, 0.54); + z-index: 100; + } + + &__header, + &__body, + &__footer { + padding: get-spacing(haapsalu); + } + + &__header { + display: flex; + align-items: center; + gap: get-spacing(haapsalu); + background-color: get-color(black-coral-0); + border-bottom: 1px solid get-color(black-coral-2); + } + + &__title { + flex: 1; + } + + &__close { + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + } + + &__body { + overflow: auto; + max-height: calc(90vh - 70px); + } + + &__footer { + border-top: 1px solid get-color(black-coral-2); + } +} diff --git a/GUI/src/components/Dialog/index.tsx b/GUI/src/components/Dialog/index.tsx new file mode 100644 index 0000000..7b2848c --- /dev/null +++ b/GUI/src/components/Dialog/index.tsx @@ -0,0 +1,45 @@ +import { FC, PropsWithChildren, ReactNode } from 'react'; +import * as RadixDialog from '@radix-ui/react-dialog'; +import { MdOutlineClose } from 'react-icons/md'; +import clsx from 'clsx'; +import './Dialog.scss'; +import Icon from 'components/Icon'; +import Track from 'components/Track'; + +type DialogProps = { + title?: string | null; + footer?: ReactNode; + onClose: () => void; + size?: 'default' | 'large'; + isOpen?: boolean; +} + +const Dialog: FC> = ({ title, footer, onClose, size = 'default', children,isOpen }) => { + return ( + + + + + { + title &&
+ {title} + + + +
+ } +
+ {children} +
+ {footer && ( + {footer} + )} +
+
+
+ ); +}; + +export default Dialog; diff --git a/GUI/src/components/Drawer/Drawer.scss b/GUI/src/components/Drawer/Drawer.scss new file mode 100644 index 0000000..df7bc71 --- /dev/null +++ b/GUI/src/components/Drawer/Drawer.scss @@ -0,0 +1,40 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.drawer { + position: fixed; + display: flex; + flex-direction: column; + top: 100px; + right: 0; + bottom: 0; + background-color: get-color(white); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.14); + width: 50%; + transition: transform .25s ease-out; + overflow: hidden; + z-index: 98; + + &__header { + display: flex; + align-items: center; + gap: get-spacing(haapsalu); + padding: get-spacing(haapsalu); + border-bottom: 1px solid get-color(black-coral-2); + + .icon { + font-size: 20px; + } + } + + &__title, + &__body { + flex: 1; + } + + &__body { + overflow: auto; + } +} diff --git a/GUI/src/components/Drawer/index.tsx b/GUI/src/components/Drawer/index.tsx new file mode 100644 index 0000000..9b6f771 --- /dev/null +++ b/GUI/src/components/Drawer/index.tsx @@ -0,0 +1,42 @@ +import { CSSProperties, FC, PropsWithChildren, useEffect, useRef } from 'react'; +import { MdOutlineClose } from 'react-icons/md'; +import autoAnimate from '@formkit/auto-animate'; + +import { Icon } from 'components'; +import './Drawer.scss'; + +type DrawerProps = { + title: string; + onClose: () => void; + style?: CSSProperties; +} + +const Drawer: FC> = ({ title, onClose, children, style }) => { + const ref = useRef(null); + + useEffect(() => { + ref.current && autoAnimate(ref.current); + const handleKeyup = (e: KeyboardEvent) => { + if (e.key === 'Escape') onClose(); + }; + document.addEventListener('keyup', handleKeyup); + + return () => document.removeEventListener('keyup', handleKeyup); + }, [onClose]); + + return ( +
+
+

{title}

+ +
+
+ {children} +
+
+ ); +}; + +export default Drawer; diff --git a/GUI/src/components/FileUpload/index.tsx b/GUI/src/components/FileUpload/index.tsx new file mode 100644 index 0000000..5750fba --- /dev/null +++ b/GUI/src/components/FileUpload/index.tsx @@ -0,0 +1,98 @@ +import { FormInput } from 'components/FormElements'; +import React, { + ChangeEvent, + forwardRef, + useImperativeHandle, + Ref, + useRef, + useState, +} from 'react'; +import { useTranslation } from 'react-i18next'; + +type FileUploadProps = { + onFileSelect: (file: File | undefined) => void; + accept?: string | string[]; + disabled?: boolean; +}; + +export type FileUploadHandle = { + clearFile: () => void; +}; + +const FileUpload = forwardRef( + (props: FileUploadProps, ref: Ref) => { + const { onFileSelect, accept, disabled } = props; + const fileInputRef = useRef(null); + const [errorMessage, setErrorMessage] = useState(''); + const { t } = useTranslation(); + useImperativeHandle(ref, () => ({ + clearFile() { + onFileSelect(undefined); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + }, + })); + + const handleFileChange = (e: ChangeEvent) => { + const file = e.target.files ? e.target.files[0] : undefined; + const maxFileSize = 20 * 1024 * 1024; // 20 MB in bytes + + if (file) { + if (file.size > maxFileSize) { + setErrorMessage(t('global.maxFileSize') ?? ''); + onFileSelect(undefined); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + } else { + setErrorMessage(''); + onFileSelect(file); + } + } else { + setErrorMessage(''); + onFileSelect(undefined); + } + }; + + const restrictFormat = (accept: string | string[]) => { + if (typeof accept === 'string') { + if (accept === 'json') return '.json'; + else if (accept === 'xlsx') return '.xlsx'; + else if (accept === 'yaml') return '.yaml, .yml'; + return ''; + } else { + return accept.map((ext) => `.${ext}`).join(', '); + } + }; + + return ( +
+ + + + {errorMessage &&

{errorMessage}

} + +
+ ); + } +); + +export default FileUpload; diff --git a/GUI/src/components/FormElements/DynamicForm/index.tsx b/GUI/src/components/FormElements/DynamicForm/index.tsx new file mode 100644 index 0000000..4e30739 --- /dev/null +++ b/GUI/src/components/FormElements/DynamicForm/index.tsx @@ -0,0 +1,110 @@ +import React, { useEffect, useState } from 'react'; +import { useForm, Controller } from 'react-hook-form'; +import FormInput from '../FormInput'; +import FormSelect from '../FormSelect'; +import Button from 'components/Button'; +import Track from 'components/Track'; +import { useTranslation } from 'react-i18next'; +import { SelectedRowPayload } from 'types/datasets'; + +type ClientOption = { label: string; value: string; agencyId: number | string }; + +type DynamicFormProps = { + formData: {itemId:string |number, dataItem: string; agencyName: string; agencyId?: number | string }; + clientOptions: ClientOption[]; + onSubmit: (data: SelectedRowPayload) => void; + setPatchUpdateModalOpen: React.Dispatch>; +}; + +const DynamicForm: React.FC = ({ + formData, + clientOptions, + onSubmit, + setPatchUpdateModalOpen, +}) => { + const { control, handleSubmit, watch, getValues } = useForm({ + defaultValues: formData, + }); + const [isChanged, setIsChanged] = useState(false); + const { t } = useTranslation(); + + const allValues = watch(); +const [selectedClientId, setSelectedClientId] = useState(formData.agencyId ?? ''); + + useEffect(() => { + const currentValues = getValues(); + setIsChanged( + currentValues.dataItem !== formData.dataItem || + currentValues.agencyId !== formData.agencyId + ); + }, [allValues, formData, getValues]); + + const handleFormSubmit = (data: any) => { + const selectedClient = clientOptions.find(opt => opt.value === data.agencyId); + onSubmit({ + itemId: formData.itemId, + dataItem: data.dataItem, + agencyId: selectedClient?.value ?? "0", + agencyName: selectedClient?.label ?? data.agencyName, + }); +}; + + return ( +
+
+ + ( + + )} + /> +
+
+ + ( + ({ + label: opt.label, + value: opt.value, + }))} + {...field} + onSelectionChange={(selected) => { + const value = typeof selected?.value === 'object' + ? (selected?.value.id ?? '') + : (selected?.value ?? ''); + setSelectedClientId(value); + field.onChange(value); + }} + defaultValue={selectedClientId} + /> + )} + /> +
+ +
+ + +
+ +
+ ); +}; + +export default DynamicForm; \ No newline at end of file diff --git a/GUI/src/components/FormElements/FormCheckbox/FormCheckbox.scss b/GUI/src/components/FormElements/FormCheckbox/FormCheckbox.scss new file mode 100644 index 0000000..8bdf863 --- /dev/null +++ b/GUI/src/components/FormElements/FormCheckbox/FormCheckbox.scss @@ -0,0 +1,57 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.checkbox { + width: 100%; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + + &__label { + display: block; + flex: 0 0 85px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__item { + input[type=checkbox] { + display: none; + + + label { + display: block; + padding-left: 32px; + position: relative; + font-size: $veera-font-size-100; + line-height: $veera-line-height-500; + + &::before { + content: ''; + display: block; + width: 16px; + height: 16px; + box-shadow: inset 0 0 0 1px get-color(black-coral-2); + border-radius: 2px; + position: absolute; + left: 4px; + top: 4px; + } + } + + &:checked { + + label { + &::before { + background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTEiIHZpZXdCb3g9IjAgMCAxNCAxMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuNzQ5NzkgOC4xMjkwNkwxLjYyMjI5IDUuMDAxNTZMMC41NjEwMzUgNi4wNjI4MUw0Ljc0OTc5IDEwLjI1MTZMMTMuNzQ5OCAxLjI1MTU2TDEyLjY4ODUgMC4xOTAzMDhMNC43NDk3OSA4LjEyOTA2WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg=='); + background-color: get-color(sapphire-blue-10); + background-repeat: no-repeat; + background-position: center; + background-size: 13px 10px; + box-shadow: inset 0 0 0 1px get-color(sapphire-blue-10); + } + } + } + } + } +} diff --git a/GUI/src/components/FormElements/FormCheckbox/index.tsx b/GUI/src/components/FormElements/FormCheckbox/index.tsx new file mode 100644 index 0000000..6664525 --- /dev/null +++ b/GUI/src/components/FormElements/FormCheckbox/index.tsx @@ -0,0 +1,39 @@ +import { forwardRef, InputHTMLAttributes, useId } from 'react'; + +import './FormCheckbox.scss'; + +type FormCheckboxType = InputHTMLAttributes & { + label: string; + name: string; + hideLabel?: boolean; + item: { + label: string; + value: string; + checked?: boolean; + }; +} + +const FormCheckbox = forwardRef(( + { + label, + name, + hideLabel, + item, + ...rest + }, + ref, +) => { + const uid = useId(); + + return ( +
+ {label && !hideLabel && } +
+ + +
+
+ ); +}); + +export default FormCheckbox; diff --git a/GUI/src/components/FormElements/FormCheckboxes/FormCheckboxes.scss b/GUI/src/components/FormElements/FormCheckboxes/FormCheckboxes.scss new file mode 100644 index 0000000..8312649 --- /dev/null +++ b/GUI/src/components/FormElements/FormCheckboxes/FormCheckboxes.scss @@ -0,0 +1,68 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.checkboxes { + display: flex; + align-items: flex-start; + gap: get-spacing(paldiski); + + &__label { + display: block; + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__wrapper { + display: flex; + flex-direction: column; + gap: 8px; + } + + &__row { + display: flex; + gap: 20px; + } + + &__item { + input[type=checkbox] { + display: none; + + + label { + display: block; + padding-left: 32px; + position: relative; + font-size: $veera-font-size-100; + line-height: $veera-line-height-500; + text-transform: capitalize; + + &::before { + content: ''; + display: block; + width: 16px; + height: 16px; + box-shadow: inset 0 0 0 1px get-color(black-coral-2); + border-radius: 2px; + position: absolute; + left: 4px; + top: 4px; + } + } + + &:checked { + + label { + &::before { + background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTEiIHZpZXdCb3g9IjAgMCAxNCAxMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuNzQ5NzkgOC4xMjkwNkwxLjYyMjI5IDUuMDAxNTZMMC41NjEwMzUgNi4wNjI4MUw0Ljc0OTc5IDEwLjI1MTZMMTMuNzQ5OCAxLjI1MTU2TDEyLjY4ODUgMC4xOTAzMDhMNC43NDk3OSA4LjEyOTA2WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg=='); + background-color: get-color(sapphire-blue-10); + background-repeat: no-repeat; + background-position: center; + background-size: 13px 10px; + box-shadow: inset 0 0 0 1px get-color(sapphire-blue-10); + } + } + } + } + } +} diff --git a/GUI/src/components/FormElements/FormCheckboxes/index.tsx b/GUI/src/components/FormElements/FormCheckboxes/index.tsx new file mode 100644 index 0000000..47d8e23 --- /dev/null +++ b/GUI/src/components/FormElements/FormCheckboxes/index.tsx @@ -0,0 +1,77 @@ +import { ChangeEvent, FC, useId, useState, useEffect } from 'react'; + +import './FormCheckboxes.scss'; + +type FormCheckboxesType = { + label: string; + name: string; + hideLabel?: boolean; + onValuesChange?: (values: Record) => void; + items: { + label: string; + value: string; + }[] |undefined; + isStack?: boolean; + error?: string; + selectedValues?: string[]; +}; + +const FormCheckboxes: FC = ({ + label, + name, + hideLabel, + onValuesChange, + items, + isStack = true, + error, + selectedValues = [], +}) => { + const id = useId(); + const [internalSelectedValues, setInternalSelectedValues] = useState(selectedValues); + + useEffect(() => { + setInternalSelectedValues(selectedValues); + }, [selectedValues]); + + const handleValuesChange = (e: ChangeEvent) => { + const { checked, value } = e.target; + + const newValues = checked + ? [...internalSelectedValues, value] + : internalSelectedValues.filter((v: string) => v !== value); + + setInternalSelectedValues(newValues); + + if (onValuesChange) onValuesChange({ [name]: newValues }); + }; + + return ( +
+
+
+ {label && !hideLabel && ( + + )} +
+ {items?.map((item, index) => ( +
+ + +
+ ))} +
+
+
+
{error &&

{error}

}
+
+ ); +}; + +export default FormCheckboxes; diff --git a/GUI/src/components/FormElements/FormDatepicker/FormDatepicker.scss b/GUI/src/components/FormElements/FormDatepicker/FormDatepicker.scss new file mode 100644 index 0000000..55ac078 --- /dev/null +++ b/GUI/src/components/FormElements/FormDatepicker/FormDatepicker.scss @@ -0,0 +1,154 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.datepicker { + $self: &; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + width: 100%; + + &__label { + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__wrapper_column { + display: flex; + flex-direction: column; + gap: 7px; + position: relative; + width: 125px; + + .icon { + position: absolute; + right: 8px; + top: 8px; + pointer-events: none; + } + } + + &__wrapper_row { + display: flex; + flex-direction: row; + gap: 7px; + position: relative; + width: 125px; + + .icon { + position: absolute; + right: 8px; + top: 8px; + pointer-events: none; + } + } + + &__error { + width: 100%; + margin-right: 6px; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + color: get-color(black-coral-20); + border-radius: $veera-radius-s; + background-color: get-color(jasper-3); + font-size: 13px; + line-height: 20px; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2); + + &::before { + content: ''; + display: block; + background-color: get-color(jasper-3); + border-left: 16px solid transparent; + border-right: 16px solid transparent; + border-bottom: 25px; + } + } + + input { + width: 100%; + display: block; + appearance: none; + background-color: get-color(white); + border: 1px solid get-color(black-coral-6); + border-radius: $veera-radius-s; + color: var(--color-black); + font-size: $veera-font-size-100; + height: 40px; + line-height: 24px; + padding: get-spacing(paldiski); + + &::placeholder { + color: get-color(black-coral-6); + } + + &:focus { + outline: none; + border-color: get-color(sapphire-blue-10); + } + } + + &--error { + input { + border-color: get-color(jasper-10); + } + } + + &--disabled & { + input { + background-color: get-color(black-coral-0); + } + } +} + +.react-datepicker { + font-family: inherit; + font-size: 14px; + border: 1px solid get-color(black-coral-6); + border-radius: 4px; + + &-popper[data-placement^=bottom] { + padding: 0; + } + + &-wrapper { + display: block; + } + + &__input-container { + display: block; + } + + &__triangle { + &::before, + &::after { + content: none !important; + } + } + + &__navigation { + width: 50px; + height: 50px; + top: 0; + + &:hover { + background-color: var(--color-bg); + } + + &--previous { + border-top-left-radius: 4px; + border-right: 1px solid var(--color-gray); + left: 0; + } + + &--next { + border-top-right-radius: 4px; + border-left: 1px solid var(--color-gray); + right: 0; + } + } +} diff --git a/GUI/src/components/FormElements/FormDatepicker/index.tsx b/GUI/src/components/FormElements/FormDatepicker/index.tsx new file mode 100644 index 0000000..1de8e63 --- /dev/null +++ b/GUI/src/components/FormElements/FormDatepicker/index.tsx @@ -0,0 +1,98 @@ +import { forwardRef, useId } from 'react'; +import ReactDatePicker, { registerLocale } from 'react-datepicker'; +import clsx from 'clsx'; +import { et } from 'date-fns/locale'; +import { ControllerRenderProps } from 'react-hook-form'; +import { + MdChevronRight, + MdChevronLeft, + MdOutlineToday, + MdOutlineSchedule, +} from 'react-icons/md'; + +import { Icon } from 'components'; +import 'react-datepicker/dist/react-datepicker.css'; +import './FormDatepicker.scss'; + +registerLocale('et-EE', et); + +type FormDatepickerProps = ControllerRenderProps & { + label: string; + name: string; + hideLabel?: boolean; + disabled?: boolean; + placeholder?: string; + timePicker?: boolean; + direction?: 'row' | 'column'; +}; + +const FormDatepicker = forwardRef( + ( + { + label, + name, + hideLabel, + disabled, + placeholder, + timePicker, + direction = 'column', + ...rest + }, + ref + ) => { + const id = useId(); + const { value, onChange } = rest; + + const datepickerClasses = clsx( + 'datepicker', + disabled && 'datepicker--disabled' + ); + + return ( +
+ {label && !hideLabel && ( + + )} +
+ } + nextMonthButtonLabel={} + aria-label={hideLabel ? label : undefined} + showTimeSelect={timePicker} + showTimeSelectOnly={timePicker} + timeIntervals={15} + timeFormat="HH:mm:ss" + timeInputLabel="" + portalId="overlay-root" + {...rest} + onChange={onChange} + /> + + ) : ( + + ) + } + size="medium" + /> +
+
+ ); + } +); + +export default FormDatepicker; diff --git a/GUI/src/components/FormElements/FormInput/FormInput.scss b/GUI/src/components/FormElements/FormInput/FormInput.scss new file mode 100644 index 0000000..3998f07 --- /dev/null +++ b/GUI/src/components/FormElements/FormInput/FormInput.scss @@ -0,0 +1,187 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.input { + $self: &; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + width: 100%; + + &__label { + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__wrapper { + flex: 1; + display: flex; + flex-direction: column; + gap: 0px; + position: relative; + + .icon { + position: absolute; + top: 10px; + right: 10px; + } + } + + &__input-container { + position: relative; + display: flex; + align-items: center; + } + + &__replace-button { + position: absolute; + right: 8px; + top: 50%; + transform: translateY(-50%); + background-color: get-color(sapphire-blue-10); + color: get-color(white); + border: none; + border-radius: $veera-radius-s; + padding: 4px 8px; + font-size: 12px; + cursor: pointer; + z-index: 2; + + &:hover { + background-color: get-color(sapphire-blue-8); + } + + &:focus { + outline: 2px solid get-color(sapphire-blue-10); + outline-offset: 2px; + } + } + + &__prefix { + position: absolute; + left: get-spacing(paldiski); + top: 9px; // Fixed position from top of input field + color: get-color(black-coral-10); + font-size: $veera-font-size-100; + line-height: 24px; + pointer-events: none; + z-index: 1; + } + + &__inline_error { + color: get-color(jasper-10); + font-size: 12px; + + } + + &__error { + width: 100%; + margin-right: 6px; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + color: get-color(black-coral-20); + border-radius: $veera-radius-s; + background-color: get-color(jasper-3); + font-size: 13px; + line-height: 20px; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2); + + &::before { + content: ''; + display: block; + background-color: get-color(jasper-3); + border-left: 16px solid transparent; + border-right: 16px solid transparent; + border-bottom: 25px; + } + } + + // Input field styles + &__field { + width: 100%; + display: block; + appearance: none; + background-color: get-color(white); + border: 1px solid get-color(black-coral-6); + border-radius: $veera-radius-s; + color: var(--color-black); + font-size: $veera-font-size-100; + height: 40px; + line-height: 24px; + padding: get-spacing(paldiski); + + &::placeholder { + color: get-color(black-coral-6); + } + + &:focus { + outline: none; + border-color: get-color(sapphire-blue-10); + } + + // Add left padding when prefix is present + &--with-prefix { + padding-left: 30px; + } + + // Add right padding when replace button is present + &--with-replace-button { + padding-right: 70px; + } + } + + // Legacy input styles for backward compatibility + input { + width: 100%; + display: block; + appearance: none; + background-color: get-color(white); + border: 1px solid get-color(black-coral-6); + border-radius: $veera-radius-s; + color: var(--color-black); + font-size: $veera-font-size-100; + height: 40px; + line-height: 24px; + padding: get-spacing(paldiski); + + &::placeholder { + color: get-color(black-coral-6); + } + + &:focus { + outline: none; + border-color: get-color(sapphire-blue-10); + } + } + + // Add left padding when prefix is present (legacy support) + &__input-container:has(&__prefix) input { + padding-left: 30px; + } + + &--error { + .input__field { + border-color: get-color(jasper-10); + } + + input { + border-color: get-color(jasper-10); + } + } + + &--disabled & { + .input__field { + background-color: get-color(black-coral-0); + border: solid 1px get-color(jasper-10); + } + + input { + background-color: get-color(black-coral-0); + border: solid 1px get-color(jasper-10); + } + } +} diff --git a/GUI/src/components/FormElements/FormInput/index.tsx b/GUI/src/components/FormElements/FormInput/index.tsx new file mode 100644 index 0000000..7d681a6 --- /dev/null +++ b/GUI/src/components/FormElements/FormInput/index.tsx @@ -0,0 +1,128 @@ +import { forwardRef, InputHTMLAttributes, PropsWithChildren, useId } from 'react'; +import clsx from 'clsx'; +import './FormInput.scss'; +import { DefaultTFuncReturn } from 'i18next'; +import { formatNumberWithCommas, removeCommasFromNumber } from 'utils/commonUtils'; + +type InputProps = PropsWithChildren> & { + label: string; + name: string; + hideLabel?: boolean; + maxLength?: number; + error?: string; + placeholder?: string | DefaultTFuncReturn; + prefix?: string; + formatAsNumber?: boolean; // New prop for number formatting + showEndButton?: boolean; // New prop for replace button + onEndButtonClick?: () => void; // New prop for replace button click handler + endButtonText?: string; // New prop for replace button text +}; + +const FormInput = forwardRef( + ( + { + label, + name, + disabled, + hideLabel, + maxLength, + error, + children, + placeholder, + prefix, + formatAsNumber, + showEndButton = false, + onEndButtonClick, + endButtonText = 'Replace', + onChange, + value, + ...rest + }, + ref + ) => { + const id = useId(); + + const handleInputChange = (e: React.ChangeEvent) => { + let newValue = e.target.value; + + if (formatAsNumber) { + // Remove any existing commas for processing + const cleanValue = removeCommasFromNumber(newValue); + + // Only allow positive numbers and decimal points + const numericValue = cleanValue.replace(/[^\d.]/g, ''); + + // Prevent multiple decimal points + const parts = numericValue.split('.'); + if (parts.length > 2) { + newValue = parts[0] + '.' + parts.slice(1).join(''); + } else { + newValue = numericValue; + } + + // Format with commas + if (newValue) { + newValue = formatNumberWithCommas(newValue); + } + + // Update the input value with formatted version + e.target.value = newValue; + } + + // Call the original onChange if provided + if (onChange) { + onChange(e); + } + }; + + // Format the value prop if formatAsNumber is enabled + const displayValue = formatAsNumber && typeof value === 'string' ? formatNumberWithCommas(value) : value; + + const inputClasses = clsx('input', disabled && 'input--disabled', error && 'input--error'); + + return ( +
+ {label && !hideLabel && ( + + )} +
+
+ {prefix && {prefix}} + + {showEndButton && ( + + )} +
+ {error &&

{error}

} + {children} +
+
+ ); + } +); + +export default FormInput; diff --git a/GUI/src/components/FormElements/FormRadios/FormRadios.scss b/GUI/src/components/FormElements/FormRadios/FormRadios.scss new file mode 100644 index 0000000..d0db7fb --- /dev/null +++ b/GUI/src/components/FormElements/FormRadios/FormRadios.scss @@ -0,0 +1,76 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.radios { + width: 100%; + display: flex; + align-items: flex-start; + gap: get-spacing(paldiski); + + &__label { + display: block; + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__wrapper { + display: flex; + gap: 8px; + } + + &__stack { + gap: 8px; + } + + &__item { + input[type=radio] { + display: none; + + + label { + display: block; + padding-left: 32px; + position: relative; + font-size: $veera-font-size-100; + line-height: $veera-line-height-500; + text-transform: capitalize; + + &::before { + content: ''; + display: block; + width: 16px; + height: 16px; + box-shadow: inset 0 0 0 1px get-color(black-coral-2); + border-radius: 50%; + position: absolute; + left: 4px; + top: 4px; + } + } + + &:checked { + + label { + &::before { + width: 20px; + height: 20px; + box-shadow: inset 0 0 0 1px #8F91A8; + } + + &::after { + content: ''; + display: block; + width: 10px; + height: 10px; + border-radius: 50%; + background-color: get-color(sapphire-blue-10); + position: absolute; + top: 9px; + left: 9px; + } + } + } + } + } +} diff --git a/GUI/src/components/FormElements/FormRadios/index.tsx b/GUI/src/components/FormElements/FormRadios/index.tsx new file mode 100644 index 0000000..9c276d4 --- /dev/null +++ b/GUI/src/components/FormElements/FormRadios/index.tsx @@ -0,0 +1,65 @@ +import { FC, useId } from 'react'; +import './FormRadios.scss'; + +type FormRadiosType = { + label: string; + name: string; + hideLabel?: boolean; + items: { + label: string; + value: string; + }[] |undefined; + onChange: (selectedValue: string) => void; + selectedValue?: string; + isStack?: boolean; + error?: string; +}; + +const FormRadios: FC = ({ + label, + name, + hideLabel, + items, + onChange, + selectedValue, + isStack = false, + error, +}) => { + const id = useId(); + + return ( +
+
+
+ {label && !hideLabel && ( + + )} +
+ {items?.map((item, index) => ( +
+ { + onChange(event.target.value); + }} + /> + +
+ ))} +
+
+
+
{error &&

{error}

}
+
+ ); +}; + +export default FormRadios; + + + + diff --git a/GUI/src/components/FormElements/FormSelect/FormMultiselect.tsx b/GUI/src/components/FormElements/FormSelect/FormMultiselect.tsx new file mode 100644 index 0000000..0ebe68d --- /dev/null +++ b/GUI/src/components/FormElements/FormSelect/FormMultiselect.tsx @@ -0,0 +1,122 @@ +import { FC, ReactNode, SelectHTMLAttributes, useId, useState } from 'react'; +import { useSelect } from 'downshift'; +import clsx from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { MdArrowDropDown } from 'react-icons/md'; + +import { Icon } from 'components'; +import './FormSelect.scss'; + +type SelectOption = { label: string, value: string }; + +type FormMultiselectProps = SelectHTMLAttributes & { + label: ReactNode; + name: string; + placeholder?: string; + hideLabel?: boolean; + options: SelectOption[]; + selectedOptions?: SelectOption[]; + onSelectionChange?: (selection: SelectOption[] | null) => void; +}; + +const FormMultiselect: FC = ( + { + label, + hideLabel, + options, + disabled, + placeholder, + defaultValue, + selectedOptions, + onSelectionChange, + ...rest + }, +) => { + const id = useId(); + const { t } = useTranslation(); + const [selectedItems, setSelectedItems] = useState(selectedOptions ?? []); + const { + isOpen, + getToggleButtonProps, + getLabelProps, + getMenuProps, + highlightedIndex, + getItemProps, + } = useSelect({ + items: options, + stateReducer: (state, actionAndChanges) => { + const { changes, type } = actionAndChanges; + if (type === useSelect.stateChangeTypes.ItemClick) { + return { + ...changes, + isOpen: true, + highlightedIndex: state.highlightedIndex, + }; + } else { + return changes; + } + }, + selectedItem: null, + onSelectedItemChange: ({ selectedItem }) => { + if (!selectedItem) { + return; + } + const index = selectedItems.findIndex((item) => item.value === selectedItem.value); + const items = []; + if (index >= 0) { + items.push( + ...selectedItems.slice(0, index), + ...selectedItems.slice(index + 1) + ); + } else { + items.push(...selectedItems, selectedItem); + } + setSelectedItems(items); + if (onSelectionChange) onSelectionChange(items); + }, + }); + + const selectClasses = clsx( + 'select', + disabled && 'select--disabled', + ); + + const placeholderValue = placeholder || t('global.choose'); + + return ( +
+ {label && !hideLabel && } +
+
+ {selectedItems?.length > 0 ? `${t('global.chosen')} (${selectedItems?.length})` : placeholderValue} + } /> +
+ +
    + {isOpen && + options.map((item, index) => ( +
  • + s.value).includes(item.value)} + value={item.value} + onChange={() => null} + /> + {item.label} +
  • + ))} +
+
+
+ ); +}; + + +export default FormMultiselect; diff --git a/GUI/src/components/FormElements/FormSelect/FormSelect.scss b/GUI/src/components/FormElements/FormSelect/FormSelect.scss new file mode 100644 index 0000000..b6b4f43 --- /dev/null +++ b/GUI/src/components/FormElements/FormSelect/FormSelect.scss @@ -0,0 +1,128 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.select { + $self: &; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + width: 100%; + + + &__label { + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__wrapper { + width: 100%; + position: relative; + } + + &__error { + border: 1px solid get-color(jasper-10); + + } + + &__default { + border: 1px solid get-color(black-coral-6); + + } + + &__trigger { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + appearance: none; + background-color: get-color(white); + border-radius: $veera-radius-s; + color: get-color(black); + font-size: $veera-font-size-100; + height: 40px; + line-height: 24px; + padding: get-spacing(paldiski); + + .icon { + font-size: $veera-font-size-250; + } + + &[aria-expanded=true] { + border-color: get-color(sapphire-blue-10); + border-radius: 3px; + + + #{$self}__menu { + display: block; + } + + +#{$self}__menu_up { + display: block; + } + + .icon { + transform: rotate(180deg); + } + } + } + + &__menu { + display: none; + position: absolute; + top: 100%; + left: 0; + right: 0; + background-color: get-color(white); + border-radius: 4px; + border: 1px solid get-color(black-coral-2); + border-top: 1; + z-index: 9998; + max-height: 320px; + overflow: auto; + margin-top: 3px; + } + + &__menu_up { + display: none; + position: absolute; + top: auto; + left: 0; + right: 0; + bottom: 100%; + background-color: get-color(white); + border-radius: 4px; + border: 1px solid get-color(black-coral-2); + border-top: 1; + z-index: 9998; + max-height: 320px; + overflow: auto; + margin-bottom: 3px; + } + + &__option { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 15px; + + span { + display: block; + } + + &[aria-selected=true] { + background-color: #DDEBFF; + + &:hover, + &:focus { + background-color: get-color(sapphire-blue-10); + } + } + + &:hover, + &:focus { + background-color: get-color(black-coral-0); + } + } +} diff --git a/GUI/src/components/FormElements/FormSelect/index.tsx b/GUI/src/components/FormElements/FormSelect/index.tsx new file mode 100644 index 0000000..e1187a4 --- /dev/null +++ b/GUI/src/components/FormElements/FormSelect/index.tsx @@ -0,0 +1,148 @@ +import { + forwardRef, + ReactNode, + SelectHTMLAttributes, + useId, + useState, + useEffect, +} from 'react'; +import { useSelect } from 'downshift'; +import clsx from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { MdArrowDropDown } from 'react-icons/md'; + +import { Icon } from 'components'; +import './FormSelect.scss'; +import { ControllerRenderProps } from 'react-hook-form'; + +type FormSelectOption = { + label: string; + value: string | { name: string; id: string }; +}; + +type FormSelectProps = Partial & + SelectHTMLAttributes & { + label: ReactNode; + name: string; + placeholder?: string; + hideLabel?: boolean; + direction?: 'down' | 'up'; + options: FormSelectOption[]; + onSelectionChange?: (selection: FormSelectOption | null) => void; + error?: string; + defaultValue?: string | { name: string; id: string } | number; + }; + +const itemToString = (item: FormSelectOption | null) => { + return item ? item.value.toString() : ''; +}; + +const FormSelect = forwardRef( + ( + { + label, + hideLabel, + direction = 'down', + options, + disabled, + placeholder, + defaultValue, + onSelectionChange, + error, + ...rest + }, + ref + ) => { + const id = useId(); + const { t } = useTranslation(); + + const [selectedItem, setSelectedItem] = useState( + options?.find((o) => o.value === defaultValue) || + options?.find( + (o) => typeof o.value === 'object' && o.value?.name === defaultValue + ) || + null + ); + + useEffect(() => { + const newSelectedItem = + options?.find((o) => o.value === defaultValue) || + options?.find( + (o) => typeof o.value === 'object' && o.value?.name === defaultValue + ) || + null; + setSelectedItem(newSelectedItem); + }, [defaultValue, options]); + + const { + isOpen, + getToggleButtonProps, + getLabelProps, + getMenuProps, + highlightedIndex, + getItemProps, + } = useSelect({ + id, + items: options, + itemToString, + selectedItem, + onSelectedItemChange: ({ selectedItem: newSelectedItem }) => { + setSelectedItem(newSelectedItem ?? null); + if (onSelectionChange) onSelectionChange(newSelectedItem ?? null); + }, + }); + + const selectClasses = clsx('select', disabled && 'select--disabled'); + + const placeholderValue = + placeholder || t('global.select'); + + return ( +
+ {label && !hideLabel && ( + + )} +
+
+ {selectedItem?.label ?? placeholderValue} + } + /> +
+
    + {isOpen && + options.map((item, index) => ( +
  • + {item.label} +
  • + ))} +
+ {error &&

{error}

} +
+
+ ); + } +); + +export default FormSelect; diff --git a/GUI/src/components/FormElements/FormTextarea/FormTextarea.scss b/GUI/src/components/FormElements/FormTextarea/FormTextarea.scss new file mode 100644 index 0000000..51750b6 --- /dev/null +++ b/GUI/src/components/FormElements/FormTextarea/FormTextarea.scss @@ -0,0 +1,109 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.textarea { + $self: &; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + width: 100%; + + &__label { + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__wrapper { + flex: 1; + display: flex; + flex-direction: column; + gap: 7px; + position: relative; + } + + &__error { + width: 100%; + margin-right: 6px; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + color: get-color(black-coral-20); + border-radius: $veera-radius-s; + background-color: get-color(jasper-3); + font-size: 13px; + line-height: 20px; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2); + + &::before { + content: ''; + display: block; + background-color: get-color(jasper-3); + border-left: 16px solid transparent; + border-right: 16px solid transparent; + border-bottom: 25px; + } + } + + &__max-length-top { + position: absolute; + top: 10px; + right: 20px; + font-size: $veera-font-size-80; + color: get-color(black-coral-12); + pointer-events: none; + } + + &__max-length-bottom { + position: absolute; + bottom: 10px; + right: 8px; + font-size: $veera-font-size-80; + color: get-color(black-coral-12); + pointer-events: none; + } + + textarea { + width: 100%; + display: block; + appearance: none; + background-color: get-color(white); + border: 1px solid get-color(black-coral-6); + border-radius: $veera-radius-s; + color: var(--color-black); + font-size: $veera-font-size-80; + line-height: $veera-line-height-500; + height: 40px; + min-height: 40px; + padding: get-spacing(paldiski); + + &::placeholder { + color: get-color(black-coral-6); + } + + &:focus { + outline: none; + border-color: get-color(sapphire-blue-10); + } + } + + &--error { + input { + border-color: get-color(jasper-10); + } + } + + &--disabled & { + input { + background-color: get-color(black-coral-0); + } + } + + &--maxlength-shown { + textarea { + padding-right: 90px; + } + } +} diff --git a/GUI/src/components/FormElements/FormTextarea/index.tsx b/GUI/src/components/FormElements/FormTextarea/index.tsx new file mode 100644 index 0000000..b1f23fe --- /dev/null +++ b/GUI/src/components/FormElements/FormTextarea/index.tsx @@ -0,0 +1,81 @@ +import { ChangeEvent, forwardRef, useId, useState } from 'react'; +import TextareaAutosize, { TextareaAutosizeProps } from 'react-textarea-autosize'; +import clsx from 'clsx'; + +import './FormTextarea.scss'; + +type TextareaProps = TextareaAutosizeProps & { + label: string; + name: string; + hideLabel?: boolean; + showMaxLength?: boolean; + maxLengthBottom?: boolean; + className?: string; +}; + +const FormTextarea = forwardRef(( + { + label, + name, + maxLength = 2000, + minRows = 3, + maxRows = 3, + disabled, + hideLabel, + showMaxLength, + maxLengthBottom, + defaultValue, + onChange, + className, + ...rest + }, + ref, +) => { + const id = useId(); + const [currentLength, setCurrentLength] = useState((typeof defaultValue === 'string' && defaultValue.length) || 0); + + const textareaClasses = clsx( + 'textarea', + disabled && 'textarea--disabled', + showMaxLength && 'textarea--maxlength-shown', + ); + + const textareaAutosizeClasses = clsx( + className, + showMaxLength && 'textarea--maxlength-shown' + ); + + const handleOnChange = (e: ChangeEvent) => { + if (showMaxLength) { + setCurrentLength(e.target.value.length); + } + }; + + return ( +
+ {label && !hideLabel && } +
+ {showMaxLength && ( +
{currentLength}/{maxLength}
+ )} + { + if (onChange) onChange(e); + handleOnChange(e); + }} + {...rest} + /> +
+
+ ); +}); + +export default FormTextarea; \ No newline at end of file diff --git a/GUI/src/components/FormElements/SearchInput/SearchInput.scss b/GUI/src/components/FormElements/SearchInput/SearchInput.scss new file mode 100644 index 0000000..a5bec7c --- /dev/null +++ b/GUI/src/components/FormElements/SearchInput/SearchInput.scss @@ -0,0 +1,36 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; + +.search-input-container { + position: relative; + width: 100%; + + .search-button { + position: absolute; + right: 0px; + background: none; + border: none; + cursor: pointer; + color: get-color(black-coral-6); + padding: 5px; + display: flex; + align-items: center; + justify-content: center; + z-index: 2; + + &:hover { + color: get-color(sapphire-blue-10); + } + + &:disabled { + color: get-color(black-coral-3); + cursor: not-allowed; + } + } + + // Add some padding to the right of the input to prevent text overlap with the icon + input { + padding-right: 40px !important; + } +} \ No newline at end of file diff --git a/GUI/src/components/FormElements/SearchInput/index.tsx b/GUI/src/components/FormElements/SearchInput/index.tsx new file mode 100644 index 0000000..7a85a47 --- /dev/null +++ b/GUI/src/components/FormElements/SearchInput/index.tsx @@ -0,0 +1,82 @@ +import { forwardRef, useState, useEffect, ChangeEvent, KeyboardEvent } from 'react'; +import { MdOutlineSearch } from 'react-icons/md'; +import { Icon, FormInput } from 'components'; +import { DefaultTFuncReturn } from 'i18next'; +import './SearchInput.scss'; + +type SearchInputProps = { + onSearch: (searchTerm: string) => void; + placeholder?: string | DefaultTFuncReturn; + initialValue?: string; + label?: string; + disabled?: boolean; + name?: string; +}; + +const SearchInput = forwardRef( + ( + { + onSearch, + placeholder = 'Search...', + initialValue = '', + label = '', + disabled = false, + name = 'search', + }, + ref + ) => { + const [searchTerm, setSearchTerm] = useState(initialValue==="all"?"":initialValue); + + // Add useEffect to update internal state when initialValue prop changes + useEffect(() => { + setSearchTerm(initialValue==="all"?"":initialValue); + }, [initialValue]); + + const handleChange = (e: ChangeEvent) => { + setSearchTerm(e.target.value); + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + onSearch(searchTerm); + } + }; + + const handleSearchClick = () => { + onSearch(searchTerm); + }; + + return ( +
+ + + +
+ ); + } +); + +export default SearchInput; \ No newline at end of file diff --git a/GUI/src/components/FormElements/Switch/Switch.scss b/GUI/src/components/FormElements/Switch/Switch.scss new file mode 100644 index 0000000..fddf67c --- /dev/null +++ b/GUI/src/components/FormElements/Switch/Switch.scss @@ -0,0 +1,68 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.switch { + $self: &; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + + &__label { + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + &__button { + display: flex; + align-items: center; + gap: 4px; + height: 40px; + isolation: isolate; + padding: 4px; + border-radius: 20px; + background-color: get-color(black-coral-1); + font-size: $veera-font-size-80; + line-height: $veera-line-height-500; + color: get-color(black-coral-12); + position: relative; + transition: background-color .25s ease-out; + + &[aria-checked=true] { + background-color: var(--active-color, get-color(sapphire-blue-10)); + color: get-color(sapphire-blue-10); + + #{$self} { + &__off { + color: get-color(white); + background: none; + } + + &__on { + color: var(--active-color, get-color(sapphire-blue-10)); + background-color: get-color(white); + } + } + } + } + + &__thumb { + display: none; + } + + &__on, + &__off { + display: flex; + border-radius: 20px; + padding: 5.5px 10px; + font-weight: $veera-font-weight-delta; + transition: all .25s ease-out; + } + + &__off { + font-weight: $veera-font-weight-delta; + background-color: get-color(white); + } +} diff --git a/GUI/src/components/FormElements/Switch/index.tsx b/GUI/src/components/FormElements/Switch/index.tsx new file mode 100644 index 0000000..ed414c7 --- /dev/null +++ b/GUI/src/components/FormElements/Switch/index.tsx @@ -0,0 +1,68 @@ +import { forwardRef, useId } from 'react'; +import * as RadixSwitch from '@radix-ui/react-switch'; +import { useTranslation } from 'react-i18next'; +import { ControllerRenderProps } from 'react-hook-form'; + +import './Switch.scss'; + +type SwitchProps = Partial & { + onLabel?: string; + offLabel?: string; + onColor?: string; + name?: string; + label: string; + checked?: boolean; + defaultChecked?: boolean; + hideLabel?: boolean; + onCheckedChange?: (checked: boolean) => void; +}; + +const Switch = forwardRef( + ( + { + onLabel, + offLabel, + onColor, + name, + label, + checked, + hideLabel, + onCheckedChange, + defaultChecked, + }, + ref + ) => { + const id = useId(); + const { t } = useTranslation(); + const onValueLabel = onLabel || t('global.on'); + const offValueLabel = offLabel || t('global.off'); + + return ( +
+ {label && !hideLabel && ( + + )} + + + {onValueLabel} + {offValueLabel} + +
+ ); + } +); + +export default Switch; diff --git a/GUI/src/components/FormElements/SwitchBox/SwitchBox.scss b/GUI/src/components/FormElements/SwitchBox/SwitchBox.scss new file mode 100644 index 0000000..2f7a049 --- /dev/null +++ b/GUI/src/components/FormElements/SwitchBox/SwitchBox.scss @@ -0,0 +1,45 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.switchbox { + $self: &; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + + &__button { + width: 48px; + height: 8px; + border-radius: 4px; + background-color: get-color(black-coral-6); + position: relative; + + &[aria-checked=true] { + background-color: get-color(sapphire-blue-4); + + #{$self} { + &__thumb { + transform: translate(24px, -50%); + background-color: get-color(sapphire-blue-10); + } + } + } + } + + &__thumb { + position: absolute; + width: 24px; + height: 24px; + border-radius: 50%; + background-color: get-color(white); + border: 1px solid get-color(black-coral-2); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.14); + left: 0; + top: 50%; + transform: translateY(-50%); + transition: all .25s ease-out; + } +} diff --git a/GUI/src/components/FormElements/SwitchBox/index.tsx b/GUI/src/components/FormElements/SwitchBox/index.tsx new file mode 100644 index 0000000..1550576 --- /dev/null +++ b/GUI/src/components/FormElements/SwitchBox/index.tsx @@ -0,0 +1,44 @@ +import { forwardRef, useId } from 'react'; +import * as RadixSwitch from '@radix-ui/react-switch'; +import { ControllerRenderProps } from 'react-hook-form'; + +import './SwitchBox.scss'; + +type SwitchBoxProps = Partial & { + name?: string; + label: string; + checked?: boolean; + hideLabel?: boolean; + onCheckedChange?: (checked: boolean) => void; +} + +const SwitchBox = forwardRef(( + { + name, + label, + checked, + hideLabel, + onCheckedChange, + }, + ref, +) => { + const id = useId(); + + return ( +
+ {label && !hideLabel && } + + + +
+ ); +}); + +export default SwitchBox; diff --git a/GUI/src/components/FormElements/index.tsx b/GUI/src/components/FormElements/index.tsx new file mode 100644 index 0000000..ac295d5 --- /dev/null +++ b/GUI/src/components/FormElements/index.tsx @@ -0,0 +1,23 @@ +import FormInput from './FormInput'; +import FormTextarea from './FormTextarea'; +import FormSelect from './FormSelect'; +import FormMultiselect from './FormSelect/FormMultiselect'; +import Switch from './Switch'; +import FormCheckboxes from './FormCheckboxes'; +import FormRadios from './FormRadios'; +import FormCheckbox from './FormCheckbox'; +import FormDatepicker from './FormDatepicker'; +import SwitchBox from './SwitchBox'; + +export { + FormInput, + FormTextarea, + FormSelect, + FormMultiselect, + Switch, + FormCheckboxes, + FormRadios, + FormCheckbox, + FormDatepicker, + SwitchBox, +}; diff --git a/GUI/src/components/Header/Header.scss b/GUI/src/components/Header/Header.scss new file mode 100644 index 0000000..542c06f --- /dev/null +++ b/GUI/src/components/Header/Header.scss @@ -0,0 +1,10 @@ +@import '@buerokratt-ria/styles/styles/tools/spacing'; +@import '@buerokratt-ria/styles/styles/tools/color'; + +.header { + height: 100px; + padding: 24px 24px 24px 42px; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.14), 0 2px 2px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.2); + background-color: get-color(white); + z-index: 99; +} diff --git a/GUI/src/components/Header/index.tsx b/GUI/src/components/Header/index.tsx new file mode 100644 index 0000000..1bc354e --- /dev/null +++ b/GUI/src/components/Header/index.tsx @@ -0,0 +1,196 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { FC, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@tanstack/react-query'; +import { AxiosError } from 'axios'; + +import { Track, Button, Dialog } from 'components'; +import useStore from 'store'; +import { useToast } from 'hooks/useToast'; +import apiDev from 'services/api-dev'; +import { useCookies } from 'react-cookie'; +import './Header.scss'; +import { useDialog } from 'hooks/useDialog'; +import { ButtonAppearanceTypes } from 'enums/commonEnums'; +import { authEndpoints } from 'utils/endpoints'; +import { authQueryKeys } from 'utils/queryKeys'; +import { UserInfo } from 'types/userInfo'; + +interface HeaderProps { + toastContext: any; + user: UserInfo | null; +} + +const Header: FC = () => { + const { t } = useTranslation(); + const userInfo = useStore((state) => state.userInfo); + const toast = useToast(); + + const { open } = useDialog(); + + const [sessionTimeOutDuration, setSessionTimeOutDuration] = + useState(30); + const [sessionTimeOutModalOpened, setSessionTimeOutModalOpened] = + useState(false); + const [sessionExtentionInProgress, setSessionExtentionInProgress] = + useState(false); + const customJwtCookieKey = 'customJwtCookie'; + + useEffect(() => { + const interval = setInterval(() => { + const expirationTimeStamp = localStorage.getItem('exp'); + if ( + expirationTimeStamp !== 'null' && + expirationTimeStamp !== null && + expirationTimeStamp !== undefined + ) { + const expirationDate = new Date(parseInt(expirationTimeStamp) ?? ''); + const currentDate = new Date(Date.now()); + if ( + expirationDate.getTime() - currentDate.getTime() <= 240000 + ) { + if (!sessionTimeOutModalOpened) { + setSessionTimeOutModalOpened(true); + setSessionTimeOutDuration(30); + } + } + } + }, 2000); + return () => clearInterval(interval); + }, [open, sessionTimeOutDuration]); + + useEffect(() => { + let timer = null; + if (sessionTimeOutModalOpened) { + timer = setInterval(() => { + setSessionTimeOutDuration((prev) => { + if (prev > 0) { + return prev - 1; + } else { + if (!sessionExtentionInProgress) handleLogout(); + return 0; + } + }); + }, 1000); + } else if (timer) { + clearInterval(timer); + } + + return () => { + if (timer) { + clearInterval(timer); + } + }; + }, [sessionTimeOutModalOpened]); + + const [, setCookie] = useCookies([customJwtCookieKey]); + + const setNewCookie = (cookieValue: string) => { + const cookieOptions = { path: '/' }; + setCookie(customJwtCookieKey, cookieValue, cookieOptions); + }; + + const extendUserSessionMutation = useMutation({ + mutationFn: async () => { + return await apiDev.get(authEndpoints.GET_EXTENDED_COOKIE()); + }, + onSuccess: (data) => { + setNewCookie(data?.data?.response); + setSessionTimeOutDuration(30); + setSessionTimeOutModalOpened(false); + setSessionExtentionInProgress(false); + refetch() + }, + onError: (error: AxiosError) => { + handleLogout(); + }, + }); + + const { refetch } = useQuery({ + queryKey: authQueryKeys.USER_DETAILS(), + onSuccess: (res: { response: UserInfo }) => { + localStorage.setItem('exp', res.response.JWTExpirationTimestamp); + useStore.getState().setUserInfo(res.response); + }, + enabled: false + }); + const logoutMutation = useMutation({ + mutationFn: () => apiDev.get(authEndpoints.LOGOUT()), + onSuccess() { + localStorage.removeItem('exp'); + window.location.href = import.meta.env.REACT_APP_CUSTOMER_SERVICE_LOGIN; + }, + onError: async (error: AxiosError) => { + toast.open({ + type: 'error', + title: t('global.notificationError'), + message: error.message, + }); + }, + }); + + const handleLogout = () => { + localStorage.removeItem('exp'); + logoutMutation.mutate(); + }; + return ( +
+
+ + {userInfo && ( + + + + )} + +
+ + {sessionTimeOutModalOpened && ( + setSessionTimeOutModalOpened(false)} + isOpen={sessionTimeOutModalOpened} + title={t('global.sessionTimeOutTitle') ?? ''} + footer={ +
+ + +
+ } + > +

+ {t('global.sessionTimeOutDesc', { + seconds: sessionTimeOutDuration, + }) ?? ''} +

+
+ )} +
+ ); +}; + +export default Header; diff --git a/GUI/src/components/Icon/Icon.scss b/GUI/src/components/Icon/Icon.scss new file mode 100644 index 0000000..ce570ac --- /dev/null +++ b/GUI/src/components/Icon/Icon.scss @@ -0,0 +1,17 @@ +@import 'src/styles/tools/spacing'; + +.icon { + display: inline-flex; + align-items: center; + justify-content: center; + + &--small { + width: get-spacing(haapsalu); + height: get-spacing(haapsalu); + } + + &--medium { + width: get-spacing(kuressaare); + height: get-spacing(kuressaare); + } +} diff --git a/GUI/src/components/Icon/index.tsx b/GUI/src/components/Icon/index.tsx new file mode 100644 index 0000000..d9ab398 --- /dev/null +++ b/GUI/src/components/Icon/index.tsx @@ -0,0 +1,26 @@ +import { CSSProperties, forwardRef, ReactNode, StyleHTMLAttributes } from 'react'; +import * as AccessibleIcon from '@radix-ui/react-accessible-icon'; +import clsx from 'clsx'; + +import './Icon.scss'; + +type IconProps = StyleHTMLAttributes & { + label?: string | null; + icon: ReactNode; + size?: 'small' | 'medium'; +}; + +const Icon = forwardRef(({ label, icon, size = 'small', ...rest }, ref) => { + const iconClasses = clsx( + 'icon', + `icon--${size}`, + ); + + return ( + + {icon} + + ); +}); + +export default Icon; diff --git a/GUI/src/components/Label/Label.scss b/GUI/src/components/Label/Label.scss new file mode 100644 index 0000000..4daeb74 --- /dev/null +++ b/GUI/src/components/Label/Label.scss @@ -0,0 +1,90 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.label { + $self: &; + display: flex; + padding: 1.5px 16px; + font-size: 12px; + font-weight: $veera-font-weight-delta; + border: 2px solid; + background-color: get-color(white); + border-radius: $veera-radius-s; + position: relative; + width: fit-content; + height: fit-content; + text-transform: capitalize; + + &--info { + color: get-color(sapphire-blue-10); + border-color: get-color(sapphire-blue-10); + + #{$self} { + &__icon { + border-color: get-color(sapphire-blue-10); + } + } + } + + &--warning { + color: get-color(dark-tangerine-10); + border-color: get-color(dark-tangerine-10); + + #{$self} { + &__icon { + border-color: get-color(dark-tangerine-10); + } + } + } + + &--error { + color: get-color(jasper-10); + border-color: get-color(jasper-10); + + #{$self} { + &__icon { + border-color: get-color(jasper-10); + } + } + } + + &--default { + color: get-color(black-coral-7); + border-color: get-color(black-coral-7); + + #{$self} { + &__icon { + border-color: get-color(black-coral-7); + } + } + } + + &--success { + color: get-color(sea-green-10); + border-color: get-color(sea-green-10); + + #{$self} { + &__icon { + border-color: get-color(sea-green-10); + } + } + } + + &__icon { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + font-size: 13px; + line-height: 15px; + right: -8px; + top: 4px; + width: 16px; + height: 16px; + border-radius: 50%; + border: 2px solid; + background-color: get-color(white); + } +} diff --git a/GUI/src/components/Label/index.tsx b/GUI/src/components/Label/index.tsx new file mode 100644 index 0000000..e27d0d4 --- /dev/null +++ b/GUI/src/components/Label/index.tsx @@ -0,0 +1,40 @@ +import { forwardRef, PropsWithChildren, ReactNode } from 'react'; +import clsx from 'clsx'; +import { MdOutlineCheck } from 'react-icons/md'; + +import { Tooltip } from 'components'; +import './Label.scss'; + +type LabelProps = { + type?: 'warning' | 'error' | 'info' | 'success' | 'default'; + tooltip?: ReactNode; +} + +const Label = forwardRef>(( + { + type = 'default', + tooltip, + children, + }, ref, +) => { + const labelClasses = clsx( + 'label', + `label--${type}`, + tooltip && 'label--tooltip', + ); + + return ( + + {children} + {tooltip && ( + + + {type === 'success' ? : 'i'} + + + )} + + ); +}); + +export default Label; diff --git a/GUI/src/components/LabelChip/index.scss b/GUI/src/components/LabelChip/index.scss new file mode 100644 index 0000000..ed40b04 --- /dev/null +++ b/GUI/src/components/LabelChip/index.scss @@ -0,0 +1,23 @@ +.label-chip { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 6px 20px; + border-radius: 16px; + background-color: #e0e0e0; + margin: 4px; + gap: 7px; +} + +.label-chip .label { + margin-right: 8px; +} + +.label-chip .button { + background: none; + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/GUI/src/components/LabelChip/index.tsx b/GUI/src/components/LabelChip/index.tsx new file mode 100644 index 0000000..146e80c --- /dev/null +++ b/GUI/src/components/LabelChip/index.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import './index.scss'; +import { MdClose } from 'react-icons/md'; + +type LabelChipProps = { + label: string; + onRemove: () => void; +}; + +const LabelChip: React.FC = ({ label, onRemove }) => { + return ( +
+ {label} + +
+ ); +}; + +export default LabelChip; diff --git a/GUI/src/components/Layout/Layout.scss b/GUI/src/components/Layout/Layout.scss new file mode 100644 index 0000000..13674f6 --- /dev/null +++ b/GUI/src/components/Layout/Layout.scss @@ -0,0 +1,28 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; + +.layout { + height: 100%; + display: flex; + + &__wrapper { + flex: 1; + display: flex; + flex-direction: column; + position: relative; + } + + &__main { + flex: 1; + display: flex; + flex-direction: column; + overflow-x: hidden; + gap: get-spacing(haapsalu); + padding: get-spacing(haapsalu); + position: absolute; + top: 100px; + left: 0; + right: 0; + bottom: 0px; + } +} diff --git a/GUI/src/components/Layout/index.tsx b/GUI/src/components/Layout/index.tsx new file mode 100644 index 0000000..c26eca4 --- /dev/null +++ b/GUI/src/components/Layout/index.tsx @@ -0,0 +1,23 @@ +import { FC } from 'react'; +import { Outlet } from 'react-router-dom'; +import useStore from 'store'; +import './Layout.scss'; +import { useToast } from '../../hooks/useToast'; +import Header from 'components/Header'; +import MainNavigation from 'components/MainNavigation'; + +const Layout: FC = () => { + return ( +
+ +
+
+
+ +
+
+
+ ); +}; + +export default Layout; diff --git a/GUI/src/components/MainNavigation/MainNavigation.scss b/GUI/src/components/MainNavigation/MainNavigation.scss new file mode 100644 index 0000000..93b2556 --- /dev/null +++ b/GUI/src/components/MainNavigation/MainNavigation.scss @@ -0,0 +1,130 @@ +@import '@buerokratt-ria/styles/styles/tools/spacing'; +@import '@buerokratt-ria/styles/styles/tools/color'; +@import '@buerokratt-ria/styles/styles/settings/variables/typography'; + +.nav { + $self: &; + width: 208px; + background-color: get-color(sapphire-blue-10); + overflow: auto; + scrollbar-width: none; + transition: width .1s ease-out; + z-index: 100; + + &::-webkit-scrollbar { + display: none; + } + + li, a, .nav__toggle, .nav__menu-toggle { + font-size: 14px; + line-height: 1.5; + } + + &__menu-toggle { + display: flex; + align-items: center; + + &:hover { + background-color: get-color(sapphire-blue-8); + } + + &:active { + background-color: get-color(sapphire-blue-7); + } + } + + a, .nav__toggle { + width: 100%; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + color: get-color(black-coral-0); + padding: 14px 8px 14px 32px; + box-shadow: inset 0 -1px 0 get-color(sapphire-blue-14); + + span:not(.icon) { + flex: 1; + display: block; + } + + &:hover { + background-color: get-color(sapphire-blue-8); + } + + &:active { + background-color: #2E78B3; + } + + &.active { + background-color: #2E78B3; + font-weight: 700; + } + } + + &__toggle { + &[aria-expanded=true] { + font-weight: 700; + + .icon { + transform: rotate(180deg); + } + + + ul { + display: block; + } + } + + &.nav__toggle--icon { + + .icon:first-child { + transform: none; + } + } + } + + &__toggle-icon { + margin-left: auto; + } + + &__menu-toggle { + display: flex; + align-items: center; + gap: get-spacing(paldiski); + width: 100%; + color: get-color(white); + padding: 14px 8px; + box-shadow: inset 0 -1px 0 get-color(sapphire-blue-14); + } + + &__submenu { + display: none; + + a, .nav__toggle { + background-color: get-color(sapphire-blue-14); + box-shadow: inset 0 -1px 0 get-color(sapphire-blue-17); + } + + #{$self} { + &__submenu { + a { + background-color: get-color(sapphire-blue-17); + box-shadow: inset 0 -1px 0 get-color(black); + padding: 14px 48px 14px 40px; + } + } + } + } +} + +.collapsed { + .nav__submenu { + visibility: hidden; + height: 0; + } + + button[aria-expanded=true] { + .icon { + transform: rotate(0deg); + } + } +} diff --git a/GUI/src/components/MainNavigation/index.tsx b/GUI/src/components/MainNavigation/index.tsx new file mode 100644 index 0000000..90dccb4 --- /dev/null +++ b/GUI/src/components/MainNavigation/index.tsx @@ -0,0 +1,136 @@ +import { FC, MouseEvent, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { NavLink, useLocation } from 'react-router-dom'; +import { MdCorporateFare, MdFileCopy, MdKeyboardArrowDown, MdOutlineDataset, MdSearch, MdSupervisorAccount } from 'react-icons/md'; +import { useQuery } from '@tanstack/react-query'; +import clsx from 'clsx'; +import { Icon } from 'components'; +import type { MenuItem } from 'types/mainNavigation'; +import './MainNavigation.scss'; +import apiDev from 'services/api-dev'; +import { userManagementEndpoints } from 'utils/endpoints'; +import { authQueryKeys } from 'utils/queryKeys'; +import { ROLES } from 'enums/roles'; + +const MainNavigation: FC = () => { + const { t } = useTranslation(); + const [menuItems, setMenuItems] = useState([]); + + const items = [ + { + id: 'userManagement', + label: t('menu.userManagement'), + path: '/user-management', + icon: , + }, + { + id: 'llmConnections', + label: t('menu.llmConnections'), + path: '/llm-connections', + icon: , + }, + { + id: 'testLLM', + label: t('menu.testLLM'), + path: '/test-llm', + icon: + }, + { + id: 'testProductionLLM', + label: 'Test Production LLM', + path: '/test-production-llm', + icon: + } + ]; + + const filterItemsByRole = (role: string[], items: MenuItem[]) => { + return items?.filter((item) => { + if (role.includes(ROLES.ROLE_ADMINISTRATOR)) return item?.id; + else if (role.includes(ROLES.ROLE_MODEL_TRAINER)) + return item?.id !== 'userManagement' && item?.id !== 'integration'; + else return false; + }); + }; + + useQuery(authQueryKeys.USER_ROLES(), { + queryFn: async () => { + const res = await apiDev.get(userManagementEndpoints.FETCH_USER_ROLES()); + return res?.data?.response; + }, + onSuccess: (res) => { + const roles = res; + const filteredItems = filterItemsByRole(roles, items); + setMenuItems(filteredItems); + }, + onError: (error) => { + console.error('Error fetching user roles:', error); + }, + }); + const location = useLocation(); + const navCollapsed = false; + + const handleNavToggle = (event: MouseEvent) => { + const isExpanded = + event?.currentTarget?.getAttribute('aria-expanded') === 'true'; + event?.currentTarget?.setAttribute( + 'aria-expanded', + isExpanded ? 'false' : 'true' + ); + }; + + const renderMenuTree = (menuItems: MenuItem[]) => { + return menuItems?.map((menuItem) => ( +
  • + {menuItem?.children ? ( +
    + +
      + {renderMenuTree(menuItem?.children)} +
    +
    + ) : ( + + {' '} + + {menuItem?.label} + + )} +
  • + )); + }; + + if (!menuItems) return null; + + return ( + + ); +}; + +export default MainNavigation; \ No newline at end of file diff --git a/GUI/src/components/Popover/Popover.scss b/GUI/src/components/Popover/Popover.scss new file mode 100644 index 0000000..9278c90 --- /dev/null +++ b/GUI/src/components/Popover/Popover.scss @@ -0,0 +1,15 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/typography'; + +.popover { + background-color: get-color(white); + padding: 4px; + border-radius: 4px; + filter: drop-shadow(0px 0px 20px rgba(0, 0, 0, 0.25)); + font-size: $veera-font-size-80; + + &__arrow { + fill: get-color(white); + } +} diff --git a/GUI/src/components/Popover/index.tsx b/GUI/src/components/Popover/index.tsx new file mode 100644 index 0000000..929015b --- /dev/null +++ b/GUI/src/components/Popover/index.tsx @@ -0,0 +1,27 @@ +import { FC, PropsWithChildren, ReactNode } from 'react'; +import * as RadixPopover from '@radix-ui/react-popover'; + +import './Popover.scss'; + +type PopoverProps = { + content: ReactNode; + defaultOpen?: boolean; +} + +const Popover: FC> = ({ children, content, defaultOpen = false }) => { + return ( + + + {children} + + + + {content} + + + + + ); +}; + +export default Popover; diff --git a/GUI/src/components/ProgressBar/index.scss b/GUI/src/components/ProgressBar/index.scss new file mode 100644 index 0000000..bc4f3a5 --- /dev/null +++ b/GUI/src/components/ProgressBar/index.scss @@ -0,0 +1,28 @@ +.progress-bar-container { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + } + + .progress-bar-label { + margin-bottom: 4px; + font-size: 14px; + } + + .progress-bar-root { + position: relative; + overflow: hidden; + background-color: #e0e0e0; + border-radius: 4px; + width: 100%; + height: 10px; + } + + .progress-bar-indicator { + background-color: #07478d; + height: 100%; + transition: width 0.3s; + border-radius: 20px; + } + \ No newline at end of file diff --git a/GUI/src/components/ProgressBar/index.tsx b/GUI/src/components/ProgressBar/index.tsx new file mode 100644 index 0000000..69d6a44 --- /dev/null +++ b/GUI/src/components/ProgressBar/index.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import * as Progress from '@radix-ui/react-progress'; +import './index.scss'; + +type ProgressBarProps = { + value: number; + max: number; + label?: string; +}; + +const ProgressBar: React.FC = ({ value, max, label }) => { + return ( +
    + + + + {label && } + +
    + ); +}; + +export default ProgressBar; diff --git a/GUI/src/components/Section/Section.scss b/GUI/src/components/Section/Section.scss new file mode 100644 index 0000000..cdbb136 --- /dev/null +++ b/GUI/src/components/Section/Section.scss @@ -0,0 +1,11 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/typography'; + +.section { + padding: get-spacing(haapsalu); + + &:not(:last-child) { + border-bottom: 1px solid get-color(black-coral-2); + } +} diff --git a/GUI/src/components/Section/index.tsx b/GUI/src/components/Section/index.tsx new file mode 100644 index 0000000..7ecd131 --- /dev/null +++ b/GUI/src/components/Section/index.tsx @@ -0,0 +1,13 @@ +import { forwardRef, PropsWithChildren } from 'react'; + +import './Section.scss'; + +const Section = forwardRef(({ children }, ref) => { + return ( +
    + {children} +
    + ); +}); + +export default Section; diff --git a/GUI/src/components/Toast/Toast.scss b/GUI/src/components/Toast/Toast.scss new file mode 100644 index 0000000..fd34091 --- /dev/null +++ b/GUI/src/components/Toast/Toast.scss @@ -0,0 +1,73 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.toast { + padding: 16px; + border-radius: 5px; + border: 1px solid; + display: flex; + flex-direction: column; + gap: 8px; + position: relative; + transition: opacity 0.25s ease-out; + + &__title { + display: flex; + align-items: center; + gap: 8px; + padding-right: 25px; + } + + &__list { + position: fixed; + bottom: 0; + right: 0; + display: flex; + flex-direction: column; + gap: 16px; + padding: 8px; + width: 408px; + max-width: 100vw; + z-index: 9999; + list-style: none; + } + + &__content { + font-size: $veera-font-size-80; + + a { + display: inline; + color: get-color(sapphire-blue-10); + text-decoration: underline; + } + } + + &__close { + position: absolute; + top: 16px; + right: 16px; + font-size: 20px; + } + + &--success { + border-color: get-color(sea-green-10); + background-color: get-color(sea-green-0); + } + + &--info { + border-color: get-color(sapphire-blue-10); + background-color: get-color(sapphire-blue-1); + } + + &--error { + border-color: get-color(jasper-10); + background-color: #FCEEEE; + } + + &--warning { + border-color: get-color(dark-tangerine-10); + background-color: get-color(dark-tangerine-1); + } +} diff --git a/GUI/src/components/Toast/index.tsx b/GUI/src/components/Toast/index.tsx new file mode 100644 index 0000000..ffa29f6 --- /dev/null +++ b/GUI/src/components/Toast/index.tsx @@ -0,0 +1,54 @@ +import { FC, useState } from 'react'; +import * as RadixToast from '@radix-ui/react-toast'; +import { + MdOutlineClose, + MdOutlineInfo, + MdCheckCircleOutline, + MdOutlineWarningAmber, + MdErrorOutline, +} from 'react-icons/md'; +import clsx from 'clsx'; + +import { Icon } from 'components'; +import type { ToastType } from 'context/ToastContext'; +import './Toast.scss'; + +type ToastProps = { + toast: ToastType; + close: () => void; +}; + +const toastIcons = { + info: , + success: , + warning: , + error: , +}; + +const Toast: FC = ({ toast, close }) => { + const [open, setOpen] = useState(true); + + const toastClasses = clsx('toast', `toast--${toast.type}`); + + return ( + + + + {toast.title} + + + {toast.message} + + + } size="medium" /> + + + ); +}; + +export default Toast; diff --git a/GUI/src/components/Tooltip/Tooltip.scss b/GUI/src/components/Tooltip/Tooltip.scss new file mode 100644 index 0000000..bd062f7 --- /dev/null +++ b/GUI/src/components/Tooltip/Tooltip.scss @@ -0,0 +1,16 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/typography'; + +.tooltip { + background-color: get-color(white); + padding: 4px; + border-radius: 4px; + filter: drop-shadow(0px 0px 20px rgba(0, 0, 0, 0.25)); + font-size: $veera-font-size-80; + max-width: 50vw; + + &__arrow { + fill: get-color(white); + } +} diff --git a/GUI/src/components/Tooltip/index.tsx b/GUI/src/components/Tooltip/index.tsx new file mode 100644 index 0000000..3cd41ac --- /dev/null +++ b/GUI/src/components/Tooltip/index.tsx @@ -0,0 +1,28 @@ +import { FC, PropsWithChildren, ReactNode } from 'react'; +import * as RadixTooltip from '@radix-ui/react-tooltip'; + +import './Tooltip.scss'; + +type TooltipProps = { + content: ReactNode; +} + +const Tooltip: FC> = ({ content, children }) => { + return ( + + + + {children} + + + + {content} + + + + + + ); +}; + +export default Tooltip; diff --git a/GUI/src/components/Track/index.tsx b/GUI/src/components/Track/index.tsx new file mode 100644 index 0000000..2b66b6e --- /dev/null +++ b/GUI/src/components/Track/index.tsx @@ -0,0 +1,57 @@ +import { FC, HTMLAttributes, PropsWithChildren } from 'react'; + +type TrackProps = HTMLAttributes & { + gap?: number; + align?: 'left' | 'center' | 'right' | 'stretch'; + justify?: 'start' | 'between' | 'center' | 'around' | 'end'; + direction?: 'horizontal' | 'vertical'; + isMultiline?: boolean; +} + +const alignMap = { + left: 'flex-start', + center: 'center', + right: 'flex-end', + stretch: 'stretch', +}; + +const justifyMap = { + start: 'flex-start', + between: 'space-between', + center: 'center', + around: 'space-around', + end: 'flex-end', +}; + +const Track: FC> = ( + { + gap = 0, + align = 'center', + justify = 'start', + direction = 'horizontal', + isMultiline = false, + children, + style, + ...rest + }, +) => { + return ( +
    + {children} +
    + ); +}; + +export default Track; diff --git a/GUI/src/components/index.tsx b/GUI/src/components/index.tsx new file mode 100644 index 0000000..5bb3b36 --- /dev/null +++ b/GUI/src/components/index.tsx @@ -0,0 +1,55 @@ +import Layout from './Layout'; +import Button from './Button'; +import Icon from './Icon'; +import Track from './Track'; +import { + FormInput, + FormTextarea, + FormSelect, + FormMultiselect, + Switch, + FormCheckboxes, + FormRadios, + FormCheckbox, + FormDatepicker, + SwitchBox, +} from './FormElements'; +import DataTable from './DataTable'; +import Tooltip from './Tooltip'; +import Card from './Card'; +import Label from './Label'; +import Toast from './Toast'; +import Popover from './Popover'; +import Collapsible from './Collapsible'; +import Box from './Box'; +import Drawer from './Drawer'; +import Dialog from './Dialog'; +import Section from './Section'; + +export { + Layout, + Button, + Icon, + Track, + Tooltip, + DataTable, + FormInput, + FormTextarea, + FormSelect, + FormMultiselect, + FormDatepicker, + Switch, + SwitchBox, + Card, + Label, + Toast, + FormCheckboxes, + FormRadios, + FormCheckbox, + Popover, + Collapsible, + Box, + Drawer, + Dialog, + Section, +}; diff --git a/GUI/src/components/molecules/BudgetBanner/BudgetBanner.scss b/GUI/src/components/molecules/BudgetBanner/BudgetBanner.scss new file mode 100644 index 0000000..6d71a8d --- /dev/null +++ b/GUI/src/components/molecules/BudgetBanner/BudgetBanner.scss @@ -0,0 +1,64 @@ +.budget-banner { + width: 100%; + padding: 20px; + margin-bottom: 20px; + border-radius: 8px; + border: 1px solid; + + &__content { + display: flex; + align-items: center; + + } + + &__message { + font-size: 16px; + font-weight: 400; + line-height: 1.4; + } + + &__description { + font-size: 14px; + font-weight: 400; + line-height: 1.4; + } + + &--warning { + background-color: #fef3cd; + border-color: #b57c00; + color: #94690d; + + .budget-banner__message { + color: #94690d; + } + } + + &--error { + background-color: #ffeaeb; + border-color: #dc3545; + color: #721c24; + + .budget-banner__message { + color: #721c24; + } + } + + // Responsive design + @media (max-width: 768px) { + padding: 10px 12px; + + &__content { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + + &__message { + font-size: 13px; + } + } +} + +.m-3 { + margin-top: .75rem !important; +} \ No newline at end of file diff --git a/GUI/src/components/molecules/BudgetBanner/index.tsx b/GUI/src/components/molecules/BudgetBanner/index.tsx new file mode 100644 index 0000000..40703c4 --- /dev/null +++ b/GUI/src/components/molecules/BudgetBanner/index.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { checkBudgetStatus, BudgetStatus } from 'services/llmConnections'; +import { llmConnectionsQueryKeys } from 'utils/queryKeys'; +import './BudgetBanner.scss'; +import Button from 'components/Button'; +import { MdOutlineGppMaybe, MdWarning } from 'react-icons/md'; + +const BudgetBanner: React.FC = () => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { data: budgetStatus } = useQuery({ + queryKey: llmConnectionsQueryKeys.budgetStatus(), + queryFn: checkBudgetStatus, + }); + + if (!budgetStatus) { + return null; + } + + const getBannerContent = (status: BudgetStatus) => { + const { used_budget_percentage, exceeded_stop_budget, exceeded_warn_budget, data } = status; + const platformKey = data?.llmPlatform === "aws" ? "aws" : "azure"; + const platformName = t(`budgetBanner.platforms.${platformKey}`); + + if (exceeded_stop_budget) { + return { + type: 'error' as const, + message: t('budgetBanner.productionDisabled'), + description: t('budgetBanner.budgetExceededDescription', { platform: platformName }), + icon: + }; + } + + if (exceeded_warn_budget) { + return { + type: 'warning' as const, + message: t('budgetBanner.budgetUsageMessage', { percentage: used_budget_percentage?.toFixed(1) }), + description: t('budgetBanner.budgetUsageDescription', { + platform: platformName, + percentage: used_budget_percentage?.toFixed(1) + }), + icon: + }; + } + + return null; // Don't show banner if within budget + }; + + const bannerContent = getBannerContent(budgetStatus); + + if (!bannerContent) { + return null; + } + + return ( +
    +
    + {bannerContent.icon} + + {bannerContent.message} + +
    + + {bannerContent.description} + +

    +
    + {budgetStatus.exceeded_warn_budget && !budgetStatus.exceeded_stop_budget ? + ( + + ) : ( + + ) + } +
    + ); +}; + +export default BudgetBanner; diff --git a/GUI/src/components/molecules/CircularSpinner/CircularSpinner.tsx b/GUI/src/components/molecules/CircularSpinner/CircularSpinner.tsx new file mode 100644 index 0000000..60eaa8a --- /dev/null +++ b/GUI/src/components/molecules/CircularSpinner/CircularSpinner.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import './Spinner.scss'; + +interface SpinnerProps { + size?: number; +} + +const CircularSpinner: React.FC = ({ size = 80 }) => { + return ( +
    +
    +
    + ); +}; + +export default CircularSpinner; \ No newline at end of file diff --git a/GUI/src/components/molecules/CircularSpinner/Spinner.scss b/GUI/src/components/molecules/CircularSpinner/Spinner.scss new file mode 100644 index 0000000..d2297de --- /dev/null +++ b/GUI/src/components/molecules/CircularSpinner/Spinner.scss @@ -0,0 +1,23 @@ +.spinner-container { + display: flex; + justify-content: center; + align-items: center; + height: 80vh; + } + + .spinner { + border: 4px solid rgba(0, 0, 0, 0.1); + border-top: 4px solid #3498db; + border-radius: 50%; + animation: spin 1s linear infinite; + } + + @keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } + } + \ No newline at end of file diff --git a/GUI/src/components/molecules/DataGenerationStatusLabel/index.tsx b/GUI/src/components/molecules/DataGenerationStatusLabel/index.tsx new file mode 100644 index 0000000..9c8425b --- /dev/null +++ b/GUI/src/components/molecules/DataGenerationStatusLabel/index.tsx @@ -0,0 +1,36 @@ +import { DataGenerationStatus } from 'enums/datasetEnums'; +import Label from 'components/Label'; +import { LabelType } from 'enums/commonEnums'; +import { useTranslation } from 'react-i18next'; + +const DataGenerationStatusLabel = ({ + status, +}: { + status: string | undefined; +}) => { + const { t } = useTranslation(); + + if (status === DataGenerationStatus.SUCCESS) { + return ( + + ); + } else if (status === DataGenerationStatus.FAILED) { + return ( + + ); + } else if (status === DataGenerationStatus.IN_PROGRESS) { + return ( + + ); + } else { + return null; + } +}; + +export default DataGenerationStatusLabel; diff --git a/GUI/src/components/molecules/LLMConnectionCard/LLMConnectionCard.scss b/GUI/src/components/molecules/LLMConnectionCard/LLMConnectionCard.scss new file mode 100644 index 0000000..2bee0d8 --- /dev/null +++ b/GUI/src/components/molecules/LLMConnectionCard/LLMConnectionCard.scss @@ -0,0 +1,51 @@ +.training-results-grid-container { + display: grid; + grid-template-columns: 3fr 1fr 1fr; + gap: 10px; +} + +.space-between { + display: flex; + gap: 1rem; + justify-content: space-between; +} + +.mt-3{ + margin-top: 3rem; +} + +.training-results-container { + overflow-y: scroll; + max-height: 70vh; +} + +.dataset-group-card { + width: 100%; + border: 1px solid #ccc; + border-radius: 8px; + background-color: #fff; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + padding: 15px; + box-sizing: border-box; +} + +.label-row { + display: flex; + gap: .5rem; + margin: 0.5rem 0rem; +} + +.button-row { + display: flex; + gap: 10px; + justify-content: end +} + +.label-title{ + font-weight: 600; + color: #686B78; +} + +.label-value{ + color: #686B78; +} \ No newline at end of file diff --git a/GUI/src/components/molecules/LLMConnectionCard/index.tsx b/GUI/src/components/molecules/LLMConnectionCard/index.tsx new file mode 100644 index 0000000..48342e7 --- /dev/null +++ b/GUI/src/components/molecules/LLMConnectionCard/index.tsx @@ -0,0 +1,167 @@ +import { FC, PropsWithChildren, useState } from 'react'; +import Button from 'components/Button'; +import Label from 'components/Label'; +import { useDialog } from 'hooks/useDialog'; +import './LLMConnectionCard.scss'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import { Switch } from 'components/FormElements'; +import { updateLLMConnectionStatus } from 'services/llmConnections'; +import { useToast } from 'hooks/useToast'; +import { ToastTypes } from 'enums/commonEnums'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { llmConnectionsQueryKeys } from 'utils/queryKeys'; +import { AxiosError } from 'axios'; + +type LLMConnectionCardProps = { + llmConnectionId: number | string; + llmConnectionName?: string; + platform?: string; + model?: string; + isActive?: boolean; + deploymentEnv?: string; + budgetStatus?: string; + onStatusChange?: (id: number | string, newStatus: boolean) => void; +}; + +const LLMConnectionCard: FC> = ({ + llmConnectionId, + llmConnectionName, + platform, + model, + isActive, + deploymentEnv, + budgetStatus, + onStatusChange, +}) => { + const { open, close } = useDialog(); + const { t } = useTranslation(); + const navigate = useNavigate(); + const toast = useToast(); + const queryClient = useQueryClient(); + + const updateStatusMutation = useMutation({ + mutationFn: ({ id, status }: { id: string | number; status: 'active' | 'inactive' }) => + updateLLMConnectionStatus(id, status), + onSuccess: async (data, variables) => { + // Invalidate queries to refresh the data + await queryClient.invalidateQueries({ + queryKey: llmConnectionsQueryKeys.all() + }); + + toast.open({ + type: ToastTypes.SUCCESS, + title: t('toast.success.title'), + message: `Connection ${variables.status === 'active' ? 'activated' : 'deactivated'} successfully`, + }); + + // Call the parent callback to update the list immediately + if (onStatusChange) { + onStatusChange(llmConnectionId, variables.status === 'active'); + } + }, + onError: (error: AxiosError) => { + console.error('Error updating connection status:', error); + toast.open({ + type: ToastTypes.ERROR, + title: t('toast.error.title'), + message: 'Failed to update connection status', + }); + }, + }); + + const handleStatusChange = async (checked: boolean) => { + if (updateStatusMutation.isLoading) return; + + const newStatus = checked ? 'active' : 'inactive'; + updateStatusMutation.mutate({ + id: llmConnectionId, + status: newStatus + }); + }; + + + const renderDeploymentEnv = (deploymentEnvironment: string | undefined) => { + if (deploymentEnvironment === "testing") { + return ( + + ); + } else if (deploymentEnvironment === "production") { + return ( + + ); + } + }; + + const renderBudgetStatus = (status: string | undefined) => { + if (status === "within_budget") { + return ( + + ); + } else if (status === "over_budget") { + return ( + + ); + } else if (status === "close_to_exceed") { + return ( + + ); + } + }; + + return ( +
    +
    +
    +

    {llmConnectionName}

    + +
    + +
    +
    + + {t('dataModels.filters.platform')}: + + {platform ?? 'N/A'} +
    +
    + + {t('dataModels.filters.model')}: + + {model ?? 'N/A'} +
    +
    + {renderDeploymentEnv(deploymentEnv)} + {renderBudgetStatus(budgetStatus)} +
    +
    +
    + +
    +
    +
    + ); +}; + +export default LLMConnectionCard; \ No newline at end of file diff --git a/GUI/src/components/molecules/LLMConnectionForm/LLMConnectionForm.scss b/GUI/src/components/molecules/LLMConnectionForm/LLMConnectionForm.scss new file mode 100644 index 0000000..c999f4a --- /dev/null +++ b/GUI/src/components/molecules/LLMConnectionForm/LLMConnectionForm.scss @@ -0,0 +1,199 @@ +.llm-connection-form { + max-width: 800px; + padding: 0rem 1.5rem; + + .form-section { + margin-bottom: 32px; + padding: 20px; + border: 1px solid #e0e0e0; + border-radius: 8px; + background-color: #fafafa; + + .form-section-title { + margin: 0 0 20px 0; + font-size: 18px; + font-weight: 600; + color: #333; + border-bottom: 2px solid #005aa3; + padding-bottom: 8px; + } + } + + .form-row { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + .radio-group { + .radio-group-label { + display: block; + margin-bottom: 12px; + font-weight: 500; + color: #333; + font-size: 14px; + } + + .radio-options { + display: flex; + flex-direction: column; + gap: 12px; + } + + .radio-option { + display: flex; + align-items: center; + cursor: pointer; + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 6px; + transition: all 0.2s ease; + + &:hover { + background-color: #f5f5f5; + border-color: #005aa3; + } + + &:has(.radio-input:checked) { + background-color: #e3f2fd; + border-color: #005aa3; + + .radio-label { + color: #005aa3; + font-weight: 500; + } + } + } + + .radio-input { + margin-right: 8px; + width: 16px; + height: 16px; + accent-color: #005aa3; + } + + .radio-label { + font-size: 14px; + color: #555; + transition: color 0.2s ease; + } + } + + .form-footer { + margin-top: 32px; + padding-top: 20px; + border-top: 1px solid #e0e0e0; + } + + .flex-grid { + display: flex; + gap: 12px; + flex-wrap: wrap; + + button { + flex: 0 1 auto; + min-width: 80px; + max-width: 100%; + } + } + + // Responsive design + // Very small screens - wrap buttons (inline buttons with wrapping) + @media (max-width: 480px) { + padding: 8px; + + .form-section { + padding: 12px; + margin-bottom: 20px; + } + + .form-footer { + margin-top: 20px; + padding-top: 12px; + } + + .flex-grid { + + flex-wrap: wrap; + gap: 8px; + justify-content: flex-end; + + button { + flex: 0 1 auto; + + min-width: 60px; + max-width: calc(50% - 4px); + padding: 8px 12px; + font-size: 13px; + } + } + } + + // Small screens - mobile + @media (min-width: 481px) and (max-width: 768px) { + padding: 12px; + + .form-section { + padding: 14px; + margin-bottom: 22px; + } + + .radio-options { + gap: 8px; + } + + .radio-option { + padding: 6px 10px; + } + + .form-footer { + margin-top: 24px; + padding-top: 16px; + } + + .flex-grid { + flex-direction: column-reverse; + gap: 12px; + + button { + width: 100%; + min-width: unset; + } + } + } + + // Medium screens - tablet + @media (min-width: 769px) and (max-width: 1024px) { + .flex-grid { + gap: 8px; + + button { + flex: 1 1 auto; + min-width: 70px; + max-width: 200px; + font-size: 14px; + padding: 8px 12px; + } + } + } +} + +// Error state styling +.input__inline_error { + color: #d32f2f; + font-size: 12px; + margin-top: 4px; + display: block; +} + +.form-label { + margin: 0; +} + +.form-description { + font-size: 12px; + color: #666; + margin-top: 4px; +} \ No newline at end of file diff --git a/GUI/src/components/molecules/LLMConnectionForm/index.tsx b/GUI/src/components/molecules/LLMConnectionForm/index.tsx new file mode 100644 index 0000000..3662097 --- /dev/null +++ b/GUI/src/components/molecules/LLMConnectionForm/index.tsx @@ -0,0 +1,884 @@ +import React, { useEffect, useState } from 'react'; +import { useForm, Controller } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { useQuery } from '@tanstack/react-query'; +import FormInput from 'components/FormElements/FormInput'; +import FormSelect from 'components/FormElements/FormSelect'; +import FormCheckbox from 'components/FormElements/FormCheckbox'; +import Button from 'components/Button'; +import Track from 'components/Track'; +import { + getLLMPlatforms, + getLLMModels, + getEmbeddingPlatforms, + getEmbeddingModels, + PlatformOption, + ModelOption +} from 'services/llmConfigs'; +import './LLMConnectionForm.scss'; +import { toOptions } from 'utils/commonUtils'; + +export type LLMConnectionFormData = { + connectionName: string; + llmPlatform: string; + llmModel: string; + embeddingModelPlatform: string; + embeddingModel: string; + monthlyBudget: string; + warnBudget: string; + stopBudget: string; + disconnectOnBudgetExceed: boolean; + deploymentEnvironment: string; + // AWS Bedrock credentials + accessKey?: string; + secretKey?: string; + // Azure credentials + deploymentName?: string; + targetUri?: string; + apiKey?: string; + // Embedding model credentials + embeddingModelApiKey?: string; + // Embedding AWS Bedrock credentials + embeddingAccessKey?: string; + embeddingSecretKey?: string; + // Embedding Azure credentials + embeddingDeploymentName?: string; + embeddingTargetUri?: string; + embeddingAzureApiKey?: string; +}; + +type LLMConnectionFormProps = { + onSubmit: (data: LLMConnectionFormData) => void; + onCancel: () => void; + onDelete: () => void; + defaultValues?: Partial; + isEditing?: boolean; + readOnly?: boolean; +}; + +const LLMConnectionForm: React.FC = ({ + onSubmit, + onCancel, + onDelete, + defaultValues, + isEditing = false, + readOnly = false, +}) => { + const { t } = useTranslation(); + const { + control, + handleSubmit, + watch, + setValue, + formState: { errors, isDirty, isValid }, + } = useForm({ + defaultValues: { + connectionName: '', + llmPlatform: '', + llmModel: '', + embeddingModelPlatform: '', + embeddingModel: '', + monthlyBudget: '', + warnBudget: '', + stopBudget: '', + disconnectOnBudgetExceed: false, + deploymentEnvironment: '', + // AWS Bedrock credentials + accessKey: '', + secretKey: '', + // Azure credentials + deploymentName: '', + targetUri: '', + apiKey: '', + // Embedding model credentials + embeddingModelApiKey: '', + // Embedding AWS Bedrock credentials + embeddingAccessKey: '', + embeddingSecretKey: '', + // Embedding Azure credentials + embeddingDeploymentName: '', + embeddingTargetUri: '', + embeddingAzureApiKey: '', + ...defaultValues, + }, + mode: 'onChange', + }); + + const selectedLLMPlatform = watch('llmPlatform'); + const selectedEmbeddingPlatform = watch('embeddingModelPlatform'); + const disconnectOnBudgetExceed = watch('disconnectOnBudgetExceed'); + + // Fetch platform and model options from API + const { data: llmPlatformsData = [], isLoading: llmPlatformsLoading, error: llmPlatformsError } = useQuery({ + queryKey: ['llm-platforms'], + queryFn: getLLMPlatforms + }); + + const { data: embeddingPlatformsData = [], isLoading: embeddingPlatformsLoading, error: embeddingPlatformsError } = useQuery({ + queryKey: ['embedding-platforms'], + queryFn: getEmbeddingPlatforms + }); + + const { data: llmModelsData = [], isLoading: llmModelsLoading, error: llmModelsError } = useQuery({ + queryKey: ['llm-models', selectedLLMPlatform], + queryFn: () => getLLMModels(selectedLLMPlatform), + enabled: !!selectedLLMPlatform, + }); + + const { data: embeddingModelsData = [], isLoading: embeddingModelsLoading, error: embeddingModelsError } = useQuery({ + queryKey: ['embedding-models', selectedEmbeddingPlatform], + queryFn: () => getEmbeddingModels(selectedEmbeddingPlatform), + enabled: !!selectedEmbeddingPlatform, + }); + +const llmPlatformOptions = toOptions(llmPlatformsData); +const embeddingPlatformOptions = toOptions(embeddingPlatformsData); +const llmModelOptions = toOptions(llmModelsData); +const embeddingModelOptions = toOptions(embeddingModelsData); + + const [apiKeyReplaceMode, setApiKeyReplaceMode] = React.useState(isEditing); + const [secretKeyReplaceMode, setSecretKeyReplaceMode] = React.useState(isEditing); + const [accessKeyReplaceMode, setAccessKeyReplaceMode] = React.useState(isEditing); + const [embeddingApiKeyReplaceMode, setEmbeddingApiKeyReplaceMode] = React.useState(isEditing); + // Embedding platform specific replace modes + const [embeddingSecretKeyReplaceMode, setEmbeddingSecretKeyReplaceMode] = React.useState(isEditing); + const [embeddingAccessKeyReplaceMode, setEmbeddingAccessKeyReplaceMode] = React.useState(isEditing); + const [embeddingAzureApiKeyReplaceMode, setEmbeddingAzureApiKeyReplaceMode] = React.useState(isEditing); + + const resetLLMCredentialFields = () => { + setValue('accessKey', ''); + setValue('secretKey', ''); + setValue('deploymentName', ''); + setValue('targetUri', ''); + setValue('apiKey', ''); + setValue('llmModel', ''); + + // Reset replace mode states when platform changes + setApiKeyReplaceMode(false); + setSecretKeyReplaceMode(false); + setAccessKeyReplaceMode(false); + }; + + const resetEmbeddingModelCredentialFields = () => { + setValue('embeddingModelApiKey', ''); + setValue('embeddingModel', ''); + // Reset embedding platform specific fields + setValue('embeddingAccessKey', ''); + setValue('embeddingSecretKey', ''); + setValue('embeddingDeploymentName', ''); + setValue('embeddingTargetUri', ''); + setValue('embeddingAzureApiKey', ''); + + // Reset replace mode states when platform changes + setEmbeddingApiKeyReplaceMode(false); + setEmbeddingSecretKeyReplaceMode(false); + setEmbeddingAccessKeyReplaceMode(false); + setEmbeddingAzureApiKeyReplaceMode(false); + }; + // Model options based on selected platform + const getLLMModelOptions = () => { + return llmModelOptions; + }; + + const getEmbeddingModelOptions = () => { + return embeddingModelOptions; + }; + + const deploymentEnvironments = [ + { label: t('llmConnectionForm.environments.testing') || 'Testing', value: 'testing' }, + { label: t('llmConnectionForm.environments.production') || 'Production', value: 'production' }, + ]; + + const renderPlatformSpecificFields = () => { + switch (selectedLLMPlatform) { + case 'aws': + return ( + <> +
    +

    {t('llmConnectionForm.aws.accessKey.label') || 'Access Key'}

    +

    {t('llmConnectionForm.aws.accessKey.description') || 'AWS Access Key for Bedrock service'}

    + ( + { + setAccessKeyReplaceMode(false); + setValue('accessKey', ''); + }} + endButtonText={t('global.change') || "Change"} + {...field} + /> + )} + /> +
    +
    +

    {t('llmConnectionForm.aws.secretKey.label') || 'Secret Key'}

    +

    {t('llmConnectionForm.aws.secretKey.description') || 'AWS Secret Key for Bedrock service'}

    + ( + { + setSecretKeyReplaceMode(false); + setValue('secretKey', ''); + }} + endButtonText={t('global.change') || "Change"} + {...field} + /> + )} + /> +
    + + ); + case 'azure': + return ( + <> +
    +

    {t('llmConnectionForm.azure.deploymentName.label') || 'Deployment Name'}

    +

    {t('llmConnectionForm.azure.deploymentName.description') || 'Azure OpenAI deployment name'}

    + ( + + )} + /> +
    +
    +

    {t('llmConnectionForm.azure.targetUri.label') || 'Endpoint / Target URI'}

    +

    {t('llmConnectionForm.azure.targetUri.description') || 'Azure OpenAI service endpoint URL'}

    + ( + + )} + /> +
    +
    +

    {t('llmConnectionForm.azure.apiKey.label') || 'API Key'}

    +

    {t('llmConnectionForm.azure.apiKey.description') || 'Azure OpenAI API key'}

    + + ( + { + setApiKeyReplaceMode(false); + setValue('apiKey', ''); + }} + endButtonText={t('global.change') || "Change"} + {...field} + /> + )} + /> +
    + + ); + + default: + return ( +
    +

    {t('llmConnectionForm.generic.llmApiKey.label') || 'LLM API Key'}

    +

    {t('llmConnectionForm.generic.llmApiKey.description') || 'The API key of the LLM model'}

    + ( + + )} + /> +
    + ); + } + }; + + const renderEmbeddingPlatformSpecificFields = () => { + switch (selectedEmbeddingPlatform) { + case 'aws': + return ( + <> +
    +

    {t('llmConnectionForm.aws.embeddingAccessKey.label') || 'Embedding Access Key'}

    +

    {t('llmConnectionForm.aws.embeddingAccessKey.description') || 'AWS Access Key for Bedrock embedding service'}

    + ( + { + setEmbeddingAccessKeyReplaceMode(false); + setValue('embeddingAccessKey', ''); + }} + endButtonText={t('global.change') || "Change"} + {...field} + /> + )} + /> +
    +
    +

    {t('llmConnectionForm.aws.embeddingSecretKey.label') || 'Embedding Secret Key'}

    +

    {t('llmConnectionForm.aws.embeddingSecretKey.description') || 'AWS Secret Key for Bedrock embedding service'}

    + ( + { + setEmbeddingSecretKeyReplaceMode(false); + setValue('embeddingSecretKey', ''); + }} + endButtonText={t('global.change') || "Change"} + {...field} + /> + )} + /> +
    + + ); + case 'azure': + return ( + <> +
    +

    {t('llmConnectionForm.azure.embeddingDeploymentName.label') || 'Embedding Deployment Name'}

    +

    {t('llmConnectionForm.azure.embeddingDeploymentName.description') || 'Azure OpenAI embedding deployment name'}

    + ( + + )} + /> +
    +
    +

    {t('llmConnectionForm.azure.embeddingTargetUri.label') || 'Embedding Endpoint / Target URI'}

    +

    {t('llmConnectionForm.azure.embeddingTargetUri.description') || 'Azure OpenAI embedding service endpoint URL'}

    + ( + + )} + /> +
    +
    +

    {t('llmConnectionForm.azure.embeddingApiKey.label') || 'Embedding API Key'}

    +

    {t('llmConnectionForm.azure.embeddingApiKey.description') || 'Azure OpenAI embedding API key'}

    + ( + { + setEmbeddingAzureApiKeyReplaceMode(false); + setValue('embeddingAzureApiKey', ''); + }} + endButtonText={t('global.change') || "Change"} + {...field} + /> + )} + /> +
    + + ); + + default: + return ( +
    +

    {t('llmConnectionForm.generic.embeddingApiKey.label') || 'Embedding Model API Key'}

    +

    {t('llmConnectionForm.generic.embeddingApiKey.description') || 'API key of your embedding model'}

    + ( + { + setEmbeddingApiKeyReplaceMode(false); + setValue('embeddingModelApiKey', ''); + }} + endButtonText={t('global.change') || "Change"} + {...field} + /> + )} + /> +
    + ); + } + }; + + const handleFormSubmit = (data: LLMConnectionFormData) => { + const cleanedData = { + ...data, + monthlyBudget: data.monthlyBudget.replace(/,/g, ''), + warnBudget: data.warnBudget.replace('%', ''), + stopBudget: data.stopBudget.replace('%', ''), + }; + onSubmit(cleanedData); + }; + + return ( +
    +
    +
    +

    {t('llmConnectionForm.sections.llmConfiguration') || 'LLM Configuration'}

    + +
    +

    {t('llmConnectionForm.fields.connectionName.label') || 'Connection Name'}

    +

    {t('llmConnectionForm.fields.connectionName.description') || 'A unique name to identify this LLM connection'}

    + ( + + )} + /> +
    + +
    +

    {t('llmConnectionForm.fields.llmPlatform.label') || 'LLM Platform'}

    +

    {t('llmConnectionForm.fields.llmPlatform.description') || 'Cloud / local platform in which your model is hosted'}

    + ( + { + field.onChange(selected?.value || ''); + resetLLMCredentialFields(); + }} + defaultValue={field.value} + {...field} + /> + )} + /> +
    + +
    +

    {t('llmConnectionForm.fields.llmModel.label') || 'LLM Model'}

    +

    {t('llmConnectionForm.fields.llmModel.description') || 'The LLM model that you want to use'}

    + + ( + { + field.onChange(selected?.value || ''); + }} + defaultValue={field.value} + {...field} + /> + )} + /> +
    + + {/* Platform-specific fields */} + {renderPlatformSpecificFields()} +
    + +
    +

    {t('llmConnectionForm.sections.embeddingConfiguration') || 'Embedding Model Configuration'}

    + +
    +

    {t('llmConnectionForm.fields.embeddingPlatform.label') || 'Embedding Model Platform'}

    +

    {t('llmConnectionForm.fields.embeddingPlatform.description') || 'This is the cloud / local platform in which your embedding model is hosted'}

    + + ( + { + field.onChange(selected?.value || ''); + resetEmbeddingModelCredentialFields(); + }} + defaultValue={field.value} + {...field} + /> + )} + /> +
    + +
    +

    {t('llmConnectionForm.fields.embeddingModel.label') || 'Embedding Model'}

    +

    {t('llmConnectionForm.fields.embeddingModel.description') || 'The embedding model that will be used for searching your knowledge base'}

    + + ( + { + field.onChange(selected?.value || ''); + }} + defaultValue={field.value} + {...field} + /> + )} + /> +
    + + {/* Embedding Platform-specific fields */} + {renderEmbeddingPlatformSpecificFields()} +
    + +
    +

    {t('llmConnectionForm.sections.budgetDeployment') || 'Budget & Deployment'}

    + +
    +

    {t('llmConnectionForm.fields.monthlyBudget.label') || 'Monthly Budget'}

    +

    {t('llmConnectionForm.fields.monthlyBudget.description') || 'Total monthly budget including embedding model and LLM model. If the LLM integration usage cost exceeds the below budget, the LLM will respond with an "inactive" status'}

    + + { + const numericValue = value.replace(/,/g, ''); + return Number(numericValue) > 0 || t('llmConnectionForm.validationMessages.monthlyBudgetPositive') || 'Monthly Budget must be a positive number'; + } + }} + render={({ field }) => ( + + )} + /> +
    + +
    + + ( + field.onChange(e.target.checked)} + hideLabel={true} + /> + )} + /> +
    + +
    +

    {t('llmConnectionForm.fields.warnBudget.label') || 'Warn Budget Threshold'}

    +

    {t('llmConnectionForm.fields.warnBudget.description') || 'You will get a notification when your usage reaches this percentage of your allocated monthly budget.'}

    + + { + const numericValue = Number(value.replace('%', '')); + + if (numericValue < 1 || numericValue > 100) { + return t('llmConnectionForm.validationMessages.warnBudgetRange') || 'Warn Budget Threshold must be between 1-100%'; + } + return true; + } + }} + render={({ field }) => ( + { + const value = e.target.value.replace(/[^\d]/g, ''); // Remove all non-numeric characters + field.onChange(value); + }} + name={field.name} + onBlur={field.onBlur} + /> + )} + /> +
    + + {disconnectOnBudgetExceed && ( +
    +

    {t('llmConnectionForm.fields.stopBudget.label') || 'Disconnect Budget Threshold'}

    +

    {t('llmConnectionForm.fields.stopBudget.description') || 'Your LLM connection will be automatically disconnected and all further requests will be stopped when your usage reaches this percentage of your monthly budget.'}

    + + { + if (!disconnectOnBudgetExceed) return true; + + const numericValue = Number(value.replace('%', '')); + const warnValue = Number(formValues.warnBudget?.replace('%', '') || 0); + + if (numericValue < 1 || numericValue > 200) { + return t('llmConnectionForm.validationMessages.stopBudgetRange') || 'Stop Budget Threshold must be between 1-200%'; + } + + if (warnValue > 0 && numericValue <= warnValue) { + return t('llmConnectionForm.validationMessages.stopBudgetGreater') || 'Stop Budget Threshold must be greater than Warn Budget Threshold'; + } + + return true; + } + }} + render={({ field }) => ( + { + const value = e.target.value.replace(/[^\d]/g, ''); // Remove all non-numeric characters + field.onChange(value); + }} + name={field.name} + onBlur={field.onBlur} + /> + )} + /> +
    + )} + +
    + ( +
    + +
    + {deploymentEnvironments?.map((env) => ( + + ))} +
    + {errors.deploymentEnvironment && ( +

    {errors.deploymentEnvironment.message}

    + )} +
    + )} + /> +
    + +
    + + {isEditing && ()} + +
    + +
    + +
    +
    + ); +}; + +export default LLMConnectionForm; diff --git a/GUI/src/components/molecules/NoDataView/NoDataView.scss b/GUI/src/components/molecules/NoDataView/NoDataView.scss new file mode 100644 index 0000000..e6bde39 --- /dev/null +++ b/GUI/src/components/molecules/NoDataView/NoDataView.scss @@ -0,0 +1,7 @@ +.p-5 { + padding: 5rem; +} + +.text-grey { + color: grey; +} diff --git a/GUI/src/components/molecules/NoDataView/index.tsx b/GUI/src/components/molecules/NoDataView/index.tsx new file mode 100644 index 0000000..c5f2bc8 --- /dev/null +++ b/GUI/src/components/molecules/NoDataView/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { MdDashboard } from 'react-icons/md'; +import './NoDataView.scss'; +interface NoDataViewProps { + text?: string; + description?: string; +} + +const NoDataView: React.FC = ({ text, description }) => { + return ( +
    + {} +
    + {text} +
    +
    +
    + {description} +
    +
    + ); +}; + +export default NoDataView; diff --git a/GUI/src/components/molecules/Pagination/Pagination.scss b/GUI/src/components/molecules/Pagination/Pagination.scss new file mode 100644 index 0000000..5c89eb8 --- /dev/null +++ b/GUI/src/components/molecules/Pagination/Pagination.scss @@ -0,0 +1,194 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/typography'; + +.data-table { + width: 100%; + color: get-color(black-coral-20); + text-align: left; + margin-bottom: 0; + display: table; + + &__scrollWrapper { + height: 100%; + overflow-x: auto; + white-space: nowrap; + display: block; + padding: 5px; + background-color: white; + border-radius: 10px; + border: solid 1px get-color(black-coral-1); + } + + thead, + tbody { + width: 100%; + } + + th { + padding: 12px 14.5px; + color: get-color(black-coral-12); + border-bottom: 1px solid get-color(black-coral-10); + font-weight: $veera-font-weight-beta; + vertical-align: middle; + position: relative; + } + + td { + padding: 12px 24px 12px 16px; + border-bottom: 1px solid get-color(black-coral-2); + vertical-align: middle; + max-width: fit-content; + + p { + white-space: break-spaces; + } + + .entity { + display: inline-flex; + align-items: center; + padding-left: 4px; + background-color: get-color(sapphire-blue-2); + border-radius: 4px; + + span { + display: inline-flex; + font-size: $veera-font-size-80; + background-color: get-color(white); + padding: 0 4px; + border-radius: 4px; + margin: 2px 2px 2px 4px; + } + } + } + + tbody { + tr { + &:last-child { + td { + border-bottom: 0; + } + } + } + } + + &__filter { + position: absolute; + top: 100%; + left: 0; + right: 0; + padding: get-spacing(paldiski); + background-color: get-color(white); + border-radius: 0 0 4px 4px; + border: 1px solid get-color(black-coral-2); + + input { + width: 100%; + display: block; + appearance: none; + background-color: get-color(white); + border: 1px solid get-color(black-coral-6); + border-radius: 5px; + color: var(--color-black); + font-size: $veera-font-size-100; + height: 32px; + line-height: 24px; + padding: get-spacing(paldiski); + + &::placeholder { + color: get-color(black-coral-6); + } + + &:focus { + outline: none; + border-color: get-color(sapphire-blue-10); + } + } + } + + &__pagination-wrapper { + display: flex; + padding: 6px 16px; + } + + &__pagination { + display: flex; + align-items: center; + gap: 15px; + margin: 0 auto; + + + .data-table__page-size { + margin-left: 0; + } + + .next, + .previous { + display: flex; + color: get-color(sapphire-blue-10); + + &[disabled] { + color: get-color(black-coral-11); + cursor: initial; + } + } + + .links { + display: flex; + align-items: center; + gap: 5px; + font-size: $veera-font-size-80; + color: get-color(black-coral-10); + + li { + display: block; + + a, + span { + display: flex; + align-items: center; + justify-content: center; + width: 25px; + height: 25px; + border-radius: 50%; + + &:hover { + text-decoration: none; + } + } + + &.active { + a, + span { + color: get-color(white); + background-color: get-color(sapphire-blue-10); + } + } + } + } + } + + &__page-size { + display: flex; + align-items: center; + gap: 8px; + font-size: $veera-font-size-80; + line-height: 16px; + color: get-color(black-coral-11); + margin-left: auto; + + select { + appearance: none; + font-size: $veera-font-size-70; + line-height: 16px; + height: 30px; + min-width: 50px; + padding: 6px 10px; + border: 1px solid #8f91a8; + border-radius: 2px; + background-color: get-color(white); + background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNiIgdmlld0JveD0iMCAwIDEwIDYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNS4zMTMwNiA1LjgwODIyQzUuMTU2ODUgNS45NjQ0MyA0LjkwMzU4IDUuOTY0NDMgNC43NDczNyA1LjgwODIyTDAuMjgyNzMgMS4zNDM1OEMwLjEyNjUyIDEuMTg3MzcgMC4xMjY1MiAwLjkzNDEwMiAwLjI4MjczIDAuNzc3ODkzTDAuNzc3NzA0IDAuMjgyOTE4QzAuOTMzOTE0IDAuMTI2NzA4IDEuMTg3MTggMC4xMjY3MDggMS4zNDMzOSAwLjI4MjkxN0w1LjAzMDIyIDMuOTY5NzRMOC43MTcwNCAwLjI4MjkxN0M4Ljg3MzI1IDAuMTI2NzA4IDkuMTI2NTIgMC4xMjY3MDggOS4yODI3MyAwLjI4MjkxN0w5Ljc3NzcgMC43Nzc4OTJDOS45MzM5MSAwLjkzNDEwMiA5LjkzMzkxIDEuMTg3MzcgOS43Nzc3IDEuMzQzNThMNS4zMTMwNiA1LjgwODIyWiIgZmlsbD0iIzU1NTg2NyIvPgo8L3N2Zz4K'); + background-repeat: no-repeat; + background-position: top 11px right 10px; + } + } +} diff --git a/GUI/src/components/molecules/Pagination/index.tsx b/GUI/src/components/molecules/Pagination/index.tsx new file mode 100644 index 0000000..7c1c3b9 --- /dev/null +++ b/GUI/src/components/molecules/Pagination/index.tsx @@ -0,0 +1,66 @@ +import React from 'react'; +import { MdOutlineWest, MdOutlineEast } from 'react-icons/md'; +import clsx from 'clsx'; +import { Link } from 'react-router-dom'; + +interface PaginationProps { + pageCount: number; + pageIndex: number; + canPreviousPage: boolean; + canNextPage: boolean; + onPageChange: (pageIndex: number) => void; + id?: string; +} + +const Pagination: React.FC = ({ + pageCount, + pageIndex, + canPreviousPage, + canNextPage, + onPageChange, + id, +}) => { + return ( +
    + {pageCount > 1 && ( +
    + + + +
    + )} +
    + ); +}; + +export default Pagination; diff --git a/GUI/src/components/molecules/ProgressBar/index.scss b/GUI/src/components/molecules/ProgressBar/index.scss new file mode 100644 index 0000000..bc4f3a5 --- /dev/null +++ b/GUI/src/components/molecules/ProgressBar/index.scss @@ -0,0 +1,28 @@ +.progress-bar-container { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + } + + .progress-bar-label { + margin-bottom: 4px; + font-size: 14px; + } + + .progress-bar-root { + position: relative; + overflow: hidden; + background-color: #e0e0e0; + border-radius: 4px; + width: 100%; + height: 10px; + } + + .progress-bar-indicator { + background-color: #07478d; + height: 100%; + transition: width 0.3s; + border-radius: 20px; + } + \ No newline at end of file diff --git a/GUI/src/components/molecules/ProgressBar/index.tsx b/GUI/src/components/molecules/ProgressBar/index.tsx new file mode 100644 index 0000000..69d6a44 --- /dev/null +++ b/GUI/src/components/molecules/ProgressBar/index.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import * as Progress from '@radix-ui/react-progress'; +import './index.scss'; + +type ProgressBarProps = { + value: number; + max: number; + label?: string; +}; + +const ProgressBar: React.FC = ({ value, max, label }) => { + return ( +
    + + + + {label && } + +
    + ); +}; + +export default ProgressBar; diff --git a/GUI/src/components/molecules/TableSkeleton/SkeletonTable.scss b/GUI/src/components/molecules/TableSkeleton/SkeletonTable.scss new file mode 100644 index 0000000..5f433ec --- /dev/null +++ b/GUI/src/components/molecules/TableSkeleton/SkeletonTable.scss @@ -0,0 +1,31 @@ +.skeleton { + display: inline-block; + height: 1.5rem; + width: 100%; + background-color: #e0e0e0; + border-radius: 4px; + animation: pulse 1.5s infinite ease-in-out; + } + + @keyframes pulse { + 0% { + background-color: #e0e0e0; + } + 50% { + background-color: #f0f0f0; + } + 100% { + background-color: #e0e0e0; + } + } + + .table { + width: 100%; + border-collapse: collapse; + } + + .table th, + .table td { + padding: 0.75rem; + text-align: left; + } \ No newline at end of file diff --git a/GUI/src/components/molecules/TableSkeleton/TableSkeleton.tsx b/GUI/src/components/molecules/TableSkeleton/TableSkeleton.tsx new file mode 100644 index 0000000..b8a23d3 --- /dev/null +++ b/GUI/src/components/molecules/TableSkeleton/TableSkeleton.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import './SkeletonTable.scss'; + +interface SkeletonTableProps { + rowCount: number; +} + +const SkeletonTable: React.FC = ({ rowCount }) => { + const skeletonRows = Array.from({ length: rowCount }, (_, index) => ( + + +
    + + + )); + + return ( + + {skeletonRows} +
    + ); +}; + +export default SkeletonTable; \ No newline at end of file diff --git a/GUI/src/components/molecules/UserManagementActionButtons/UserManagementActionButtons.tsx b/GUI/src/components/molecules/UserManagementActionButtons/UserManagementActionButtons.tsx new file mode 100644 index 0000000..4af03cc --- /dev/null +++ b/GUI/src/components/molecules/UserManagementActionButtons/UserManagementActionButtons.tsx @@ -0,0 +1,91 @@ +import { FC } from 'react'; +import Button from 'components/Button'; +import Icon from 'components/Icon'; +import { useTranslation } from 'react-i18next'; +import { MdOutlineDeleteOutline, MdOutlineEdit } from 'react-icons/md'; +import { User } from 'types/user'; +import { ButtonAppearanceTypes, ToastTypes } from 'enums/commonEnums'; +import { useDialog } from 'hooks/useDialog'; +import { deleteUser } from 'services/users'; +import { userManagementQueryKeys } from 'utils/queryKeys'; +import { useToast } from 'hooks/useToast'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { AxiosError } from 'axios'; + +const ActionButtons: FC<{ + row: User; + setEditableRow: React.Dispatch>; +}> = ({ row, setEditableRow }) => { + const { t } = useTranslation(); + const { open, close } = useDialog(); + const toast = useToast(); + const queryClient = useQueryClient(); + + const deleteUserMutation = useMutation({ + mutationFn: ({ id }: { id: string | number }) => deleteUser(id), + onSuccess: async () => { + close(); + await queryClient.invalidateQueries( + userManagementQueryKeys.getAllEmployees() + ); + toast.open({ + type: ToastTypes.SUCCESS, + title: t('global.notification'), + message: t('toast.success.userDeleted'), + }); + }, + onError: (error: AxiosError) => { + toast.open({ + type: ToastTypes.ERROR, + title: t('global.notificationError'), + message: error?.message ?? '', + }); + }, + }); + + return ( +
    + + + +
    + ), + }); + }} + > + } /> + {t('global.delete')} + + + ); +}; + +export default ActionButtons; diff --git a/GUI/src/config/dataModelsConfig.ts b/GUI/src/config/dataModelsConfig.ts new file mode 100644 index 0000000..b8d8f88 --- /dev/null +++ b/GUI/src/config/dataModelsConfig.ts @@ -0,0 +1,14 @@ +export const platforms = + [ + {label: 'Active', value: 'active'}, + {label: 'Deprecated', value: 'deprecated'}, + ] + +export const trainingStatuses = + [ + {label: 'Trained', value: 'trained'}, + {label: 'Not Trained', value: 'not_trained'}, + {label: 'Training in Progress', value: 'training_in_progress'}, + {label: 'Retraining Needed', value: 'retraining_needed'}, + {label: 'Training Failed', value: 'training_failed'} + ] diff --git a/GUI/src/config/rolesConfig.json b/GUI/src/config/rolesConfig.json new file mode 100644 index 0000000..02b429c --- /dev/null +++ b/GUI/src/config/rolesConfig.json @@ -0,0 +1,4 @@ +[ + { "label": "ROLE_ADMINISTRATOR", "value": "ROLE_ADMINISTRATOR" }, + { "label": "ROLE_MODEL_TRAINER", "value": "ROLE_MODEL_TRAINER" } +] diff --git a/GUI/src/constants/config.ts b/GUI/src/constants/config.ts new file mode 100644 index 0000000..5c0855f --- /dev/null +++ b/GUI/src/constants/config.ts @@ -0,0 +1,5 @@ +export const EMERGENCY_NOTICE_LENGTH = 250; +export const WELCOME_MESSAGE_LENGTH = 250; +export const USER_IDLE_STATUS_TIMEOUT = 300000; // milliseconds +export const CHAT_INPUT_LENGTH = 500; +export const CHAT_HISTORY_PREFERENCES_KEY = 'chat-history-preferences'; diff --git a/GUI/src/constants/menuIcons.tsx b/GUI/src/constants/menuIcons.tsx new file mode 100644 index 0000000..a53fc7c --- /dev/null +++ b/GUI/src/constants/menuIcons.tsx @@ -0,0 +1,24 @@ +import { MdOutlineForum, MdOutlineAdb, MdOutlineEqualizer, MdSettings, MdOutlineMonitorWeight } from 'react-icons/md'; + +export const menuIcons = [ + { + id: 'userManagement', + icon: , + }, + { + id: 'training', + icon: , + }, + { + id: 'analytics', + icon: , + }, + { + id: 'settings', + icon: , + }, + { + id: 'monitoring', + icon: , + }, +]; diff --git a/GUI/src/context/DialogContext.tsx b/GUI/src/context/DialogContext.tsx new file mode 100644 index 0000000..f2b75c4 --- /dev/null +++ b/GUI/src/context/DialogContext.tsx @@ -0,0 +1,83 @@ +import React, { + createContext, + FC, + PropsWithChildren, + ReactNode, + useMemo, + useState, +} from 'react'; +import * as RadixDialog from '@radix-ui/react-dialog'; +import { MdOutlineClose } from 'react-icons/md'; +import clsx from 'clsx'; +import '../components/Dialog/Dialog.scss'; +import Icon from 'components/Icon'; +import Track from 'components/Track'; + +type DialogProps = { + title?: string | null; + footer?: ReactNode; + size?: 'default' | 'large'; + content: ReactNode; +}; + +type DialogContextType = { + open: (dialog: DialogProps) => void; + close: () => void; +}; +// operates Dialog modals where dynamic contents not involved +export const DialogContext = createContext(null!); + +export const DialogProvider: FC> = ({ children }) => { + const [isOpen, setIsOpen] = useState(false); + const [dialogProps, setDialogProps] = useState(null); + + const open = (dialog: DialogProps) => { + setDialogProps(dialog); + setIsOpen(true); + }; + + const close = () => { + setIsOpen(false); + setDialogProps(null); + }; + + const contextValue = useMemo(() => ({ open, close }), []); + + return ( + + {children} + {dialogProps && ( + + + + + {dialogProps.title && ( +
    + + {dialogProps.title} + + + + +
    + )} +
    {dialogProps.content}
    + {dialogProps.footer && ( + + {dialogProps.footer} + + )} +
    +
    +
    + )} +
    + ); +}; diff --git a/GUI/src/context/ToastContext.tsx b/GUI/src/context/ToastContext.tsx new file mode 100644 index 0000000..5c07ef4 --- /dev/null +++ b/GUI/src/context/ToastContext.tsx @@ -0,0 +1,58 @@ +import { + createContext, + FC, + PropsWithChildren, + ReactNode, + useMemo, + useState, +} from 'react'; +import { useTranslation } from 'react-i18next'; +import * as RadixToast from '@radix-ui/react-toast'; + +import { Toast } from 'components'; +import { generateUEID } from 'utils/generateUEID'; + +export type ToastType = { + type: 'info' | 'success' | 'error' | 'warning'; + title: string; + message: ReactNode; +}; + +type ToastTypeWithId = ToastType & { id: string }; + +type ToastContextType = { + open: (toast: ToastType) => void; +}; + +export const ToastContext = createContext(null!); + +export const ToastProvider: FC = ({ children }) => { + const { t } = useTranslation(); + const [toasts, setToasts] = useState([]); + const open = (content: ToastType) => { + setToasts((prevState) => [ + ...prevState, + { id: generateUEID(), ...content }, + ]); + }; + const close = (id: string) => { + setToasts((prevState) => prevState.filter((toast) => toast.id === id)); + }; + + const contextValue = useMemo(() => ({ open }), []); + + return ( + + + {children} + {toasts.map((toast) => ( + close(toast.id)} /> + ))} + + + + ); +}; diff --git a/GUI/src/enums/commonEnums.ts b/GUI/src/enums/commonEnums.ts new file mode 100644 index 0000000..79f9444 --- /dev/null +++ b/GUI/src/enums/commonEnums.ts @@ -0,0 +1,18 @@ +export enum ToastTypes { + SUCCESS = 'success', + ERROR = 'error', +} + +export enum ButtonAppearanceTypes { + PRIMARY = 'primary', + SECONDARY = 'secondary', + ERROR = 'error', + TEXT = 'text', +} + +export enum LabelType { + SUCCESS = 'success', + ERROR = 'error', + INFO = 'info', + WARNING = 'warning', +} diff --git a/GUI/src/enums/roles.ts b/GUI/src/enums/roles.ts new file mode 100644 index 0000000..b5cfd8a --- /dev/null +++ b/GUI/src/enums/roles.ts @@ -0,0 +1,4 @@ +export enum ROLES { + ROLE_ADMINISTRATOR = 'ROLE_ADMINISTRATOR', + ROLE_MODEL_TRAINER = 'ROLE_MODEL_TRAINER', +} diff --git a/GUI/src/hoc/with-authorization.tsx b/GUI/src/hoc/with-authorization.tsx new file mode 100644 index 0000000..9874ffa --- /dev/null +++ b/GUI/src/hoc/with-authorization.tsx @@ -0,0 +1,29 @@ +import { ROLES } from 'enums/roles'; +import React from 'react'; +import useStore from 'store'; + +function withAuthorization

    ( + WrappedComponent: React.ComponentType

    , + allowedRoles: ROLES[] = [] +): React.FC

    { + const CheckRoles: React.FC

    = ({ ...props }: P) => { + const userInfo = useStore((x) => x.userInfo); + const allowed = allowedRoles?.some((x) => + userInfo?.authorities.includes(x) + ); + + if (!userInfo) { + return Loading...; + } + + if (!allowed) { + return Unauthorized Access; + } + + return ; + }; + + return CheckRoles; +} + +export default withAuthorization; diff --git a/GUI/src/hooks/useDialog.tsx b/GUI/src/hooks/useDialog.tsx new file mode 100644 index 0000000..c38ed60 --- /dev/null +++ b/GUI/src/hooks/useDialog.tsx @@ -0,0 +1,4 @@ +import { DialogContext } from 'context/DialogContext'; +import { useContext } from 'react'; + +export const useDialog = () => useContext(DialogContext); diff --git a/GUI/src/hooks/useDocumentEscapeListener.tsx b/GUI/src/hooks/useDocumentEscapeListener.tsx new file mode 100644 index 0000000..8f7b3b6 --- /dev/null +++ b/GUI/src/hooks/useDocumentEscapeListener.tsx @@ -0,0 +1,17 @@ +import { useLayoutEffect } from 'react'; + +const useDocumentEscapeListener = (callback: () => void) => { + useLayoutEffect(() => { + const handleKeyUp = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + callback(); + } + }; + + document.addEventListener('keyup', handleKeyUp); + + return () => document.removeEventListener('keyup', handleKeyUp); + }, [callback]); +}; + +export default useDocumentEscapeListener; diff --git a/GUI/src/hooks/useOptionLists.tsx b/GUI/src/hooks/useOptionLists.tsx new file mode 100644 index 0000000..f860f16 --- /dev/null +++ b/GUI/src/hooks/useOptionLists.tsx @@ -0,0 +1,26 @@ +import { useTranslation } from 'react-i18next'; + +// maps translations with dropdown options +const useOptionLists = () => { + const { t } = useTranslation(); + + const dataTypesConfigs = [ + { label: t('optionLists.text'), value: 'text' }, + { label: t('optionLists.numbers'), value: 'numbers' }, + { label: t('optionLists.dateTimes'), value: 'datetime' }, + { label: t('optionLists.email'), value: 'email' }, + { label: t('optionLists.fileAttachements'), value: 'file_attachments' }, + ]; + + const importOptionsConfigs = [ + { label: t('optionLists.importToAdd'), value: 'add' }, + { label: t('optionLists.importToDelete'), value: 'delete' }, + ]; + + return { + dataTypesConfigs, + importOptionsConfigs, + }; +}; + +export default useOptionLists; diff --git a/GUI/src/hooks/useToast.tsx b/GUI/src/hooks/useToast.tsx new file mode 100644 index 0000000..5171554 --- /dev/null +++ b/GUI/src/hooks/useToast.tsx @@ -0,0 +1,5 @@ +import { useContext } from 'react'; + +import { ToastContext } from 'context/ToastContext'; + +export const useToast = () => useContext(ToastContext); diff --git a/GUI/src/main.tsx b/GUI/src/main.tsx new file mode 100644 index 0000000..a44091f --- /dev/null +++ b/GUI/src/main.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { BrowserRouter } from 'react-router-dom'; +import { + QueryClient, + QueryClientProvider, + QueryFunction, +} from '@tanstack/react-query'; + +import App from './App'; +import api from 'services/api'; +import apiDev from 'services/api-dev'; +import { ToastProvider } from 'context/ToastContext'; +import 'styles/main.scss'; +import '../i18n'; +import { CookiesProvider } from 'react-cookie'; +import { DialogProvider } from 'context/DialogContext'; + +const defaultQueryFn: QueryFunction | undefined = async ({ queryKey }) => { + if (queryKey.includes('prod')) { + const { data } = await apiDev.get(queryKey[0] as string); + return data; + } + + const { data } = await api.get(queryKey[0] as string); + return data; +}; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + queryFn: defaultQueryFn, + }, + }, +}); + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + + + + + + + + + + + +); diff --git a/GUI/src/mockData/llmConnectionData.ts b/GUI/src/mockData/llmConnectionData.ts new file mode 100644 index 0000000..ccf19af --- /dev/null +++ b/GUI/src/mockData/llmConnectionData.ts @@ -0,0 +1,218 @@ +export interface LLMConnectionData { + llmConnectionId: number | string; + llmConnectionName?: string; + datasetVersion?: string; + platform?: string; + model?: boolean; + isActive?: boolean; + deploymentEnv?: string; + budgetStatus?: string; + // Form data for detailed view + llmPlatform?: string; + llmModel?: string; + embeddingModelPlatform?: string; + embeddingModel?: string; + llmApiKey?: string; + embeddingApiKey?: string; + monthlyBudget?: string; + deploymentEnvironment?: string; +} + +export const mockLLMConnections: LLMConnectionData[] = [ + { + llmConnectionId: 1, + llmConnectionName: "OpenAI GPT-4 Connection", + datasetVersion: "v2.1.0", + platform: "OpenAI", + model: true, + isActive: true, + deploymentEnv: "Production", + budgetStatus: "within" + }, + { + llmConnectionId: 2, + llmConnectionName: "Claude 3 Sonnet Integration", + datasetVersion: "v1.8.5", + platform: "Anthropic", + model: true, + isActive: false, + deploymentEnv: "Staging", + budgetStatus: "close" + }, + { + llmConnectionId: 3, + llmConnectionName: "Azure OpenAI Service", + datasetVersion: "v2.0.3", + platform: "Microsoft Azure", + model: true, + isActive: true, + deploymentEnv: "Production", + budgetStatus: "over" + }, + { + llmConnectionId: "conn-4", + llmConnectionName: "Local Llama 2 Model", + datasetVersion: "v1.5.2", + platform: "Local", + model: false, + isActive: true, + deploymentEnv: "Development", + budgetStatus: "within" + }, + { + llmConnectionId: 5, + llmConnectionName: "Google PaLM API", + datasetVersion: "v1.9.1", + platform: "Google Cloud", + model: true, + isActive: false, + deploymentEnv: "Testing", + budgetStatus: "within" + }, + { + llmConnectionId: 6, + llmConnectionName: "Cohere Command Model", + datasetVersion: "v2.2.0", + platform: "Cohere", + model: true, + isActive: true, + deploymentEnv: "Production", + budgetStatus: "close" + }, + { + llmConnectionId: "conn-7", + llmConnectionName: "Hugging Face Transformers", + datasetVersion: "v1.7.8", + platform: "Hugging Face", + model: false, + isActive: false, + deploymentEnv: "Development", + budgetStatus: "within" + }, + { + llmConnectionId: 8, + llmConnectionName: "AWS Bedrock Claude", + datasetVersion: "v2.0.7", + platform: "AWS Bedrock", + model: true, + isActive: true, + deploymentEnv: "Production", + budgetStatus: "over" + } +]; + +// Example usage with a single connection +export const singleMockConnection: LLMConnectionData = { + llmConnectionId: "demo-1", + llmConnectionName: "Demo LLM Connection", + datasetVersion: "v1.0.0", + platform: "Demo Platform", + model: true, + isActive: true, + deploymentEnv: "Demo", + budgetStatus: "within" +}; + +// Helper function to get detailed connection data for forms +export const getDetailedConnectionData = (connectionId: string | number) => { + const connection = mockLLMConnections.find( + conn => conn.llmConnectionId.toString() === connectionId.toString() + ); + + if (!connection) return null; + + // Map basic connection data to detailed form data + const detailedData: Record = { + 1: { + llmPlatform: "openai", + llmModel: "gpt-4", + embeddingModelPlatform: "openai", + embeddingModel: "text-embedding-3-large", + llmApiKey: "sk-***************************", + embeddingApiKey: "sk-***************************", + monthlyBudget: "500", + deploymentEnvironment: "production" + }, + 2: { + llmPlatform: "anthropic", + llmModel: "claude-3-sonnet", + embeddingModelPlatform: "cohere", + embeddingModel: "embed-english-v3.0", + llmApiKey: "sk-ant-*********************", + embeddingApiKey: "***************************", + monthlyBudget: "300", + deploymentEnvironment: "testing" + }, + 3: { + llmPlatform: "azure", + llmModel: "gpt-4-turbo", + embeddingModelPlatform: "azure", + embeddingModel: "text-embedding-ada-002", + llmApiKey: "***************************", + embeddingApiKey: "***************************", + monthlyBudget: "800", + deploymentEnvironment: "production" + }, + "conn-4": { + llmPlatform: "local", + llmModel: "custom", + embeddingModelPlatform: "local", + embeddingModel: "custom", + llmApiKey: "local-api-key", + embeddingApiKey: "local-embedding-key", + monthlyBudget: "0", + deploymentEnvironment: "testing" + }, + 5: { + llmPlatform: "google", + llmModel: "palm-2", + embeddingModelPlatform: "google", + embeddingModel: "textembedding-gecko", + llmApiKey: "AIza***************************", + embeddingApiKey: "AIza***************************", + monthlyBudget: "400", + deploymentEnvironment: "testing" + }, + 6: { + llmPlatform: "cohere", + llmModel: "command", + embeddingModelPlatform: "cohere", + embeddingModel: "embed-english-v3.0", + llmApiKey: "***************************", + embeddingApiKey: "***************************", + monthlyBudget: "250", + deploymentEnvironment: "production" + }, + "conn-7": { + llmPlatform: "huggingface", + llmModel: "custom-transformers", + embeddingModelPlatform: "huggingface", + embeddingModel: "sentence-transformers", + llmApiKey: "hf_***************************", + embeddingApiKey: "hf_***************************", + monthlyBudget: "100", + deploymentEnvironment: "development" + }, + 8: { + llmPlatform: "aws", + llmModel: "claude-3-sonnet", + embeddingModelPlatform: "aws", + embeddingModel: "titan-embed-text-v1", + llmApiKey: "AKIA***************************", + embeddingApiKey: "AKIA***************************", + monthlyBudget: "600", + deploymentEnvironment: "production" + } + }; + + return detailedData[connectionId] || { + llmPlatform: "", + llmModel: "", + embeddingModelPlatform: "", + embeddingModel: "", + llmApiKey: "", + embeddingApiKey: "", + monthlyBudget: "", + deploymentEnvironment: "testing" + }; +}; diff --git a/GUI/src/model/ruuter-response-model.ts b/GUI/src/model/ruuter-response-model.ts new file mode 100644 index 0000000..07cafc1 --- /dev/null +++ b/GUI/src/model/ruuter-response-model.ts @@ -0,0 +1,11 @@ +export interface RuuterResponse { + data: Record | null; + error: string | null; +} + +export interface CustomJwtExtendResponse { + data: { + custom_jwt_extend: string; + }; + error: null; +} diff --git a/GUI/src/pages/LLMConnections/CreateLLMConnection.tsx b/GUI/src/pages/LLMConnections/CreateLLMConnection.tsx new file mode 100644 index 0000000..3f2a901 --- /dev/null +++ b/GUI/src/pages/LLMConnections/CreateLLMConnection.tsx @@ -0,0 +1,127 @@ +import BackArrowButton from "assets/BackArrowButton"; +import LLMConnectionForm, { LLMConnectionFormData } from "components/molecules/LLMConnectionForm"; +import { Link, useNavigate } from "react-router-dom"; +import { useMutation, useQueryClient, useQuery } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { useDialog } from 'hooks/useDialog'; +import { createLLMConnection, getProductionConnection } from 'services/llmConnections'; +import { llmConnectionsQueryKeys } from 'utils/queryKeys'; +import { ButtonAppearanceTypes } from 'enums/commonEnums'; +import { Button } from 'components'; + +const CreateLLMConnection = () => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { open: openDialog, close: closeDialog } = useDialog(); + const queryClient = useQueryClient(); + + // Query to check for existing production connection + const { data: existingProductionConnection } = useQuery({ + queryKey: llmConnectionsQueryKeys.production(), + queryFn: () => getProductionConnection(), + }); + + const createConnectionMutation = useMutation({ + mutationFn: createLLMConnection, + onSuccess: async () => { + await queryClient.invalidateQueries({ + queryKey: llmConnectionsQueryKeys.all() + }); + + openDialog({ + title: t('llmConnectionForm.createConnection.successDialogTitle') || 'Connection Succeeded', + content:

    {t('llmConnectionForm.createConnection.successDialogMessage') || 'The provided LLM configuration is successfully configured'}

    , + footer: ( + + ), + }); + }, + onError: (error: any) => { + console.error('Error creating LLM connection:', error); + openDialog({ + title: t('llmConnectionForm.createConnection.errorDialogTitle') || 'Connection Failed', + content:

    {t('llmConnectionForm.createConnection.errorDialogMessage') || 'The connection couldn\'t be established either due to invalid API credentials or misconfiguration in the deployment platform'}

    , + footer: ( + + ), + }); + }, + }); + + const handleSubmit = async (data: LLMConnectionFormData) => { + const isCreatingProductionConnection = data.deploymentEnvironment === 'production'; + const hasExistingProductionConnection = existingProductionConnection && existingProductionConnection.id; + + if (isCreatingProductionConnection && hasExistingProductionConnection) { + openDialog({ + title: t('llmConnectionForm.createConnection.replaceProductionDialogTitle') || 'Replace Production Connection', + content: ( +
    +

    {t('llmConnectionForm.createConnection.replaceProductionDialogMessage', { connectionName: existingProductionConnection.connectionName }) || `A production connection "${existingProductionConnection.connectionName}" already exists.`}

    +

    {t('llmConnectionForm.createConnection.replaceProductionDialogWarning') || 'Creating this new production connection will replace the current one. Are you sure you want to proceed?'}

    +
    + ), + footer: ( +
    + + +
    + ), + }); + } else { + createConnectionMutation.mutate(data); + } + }; + + const handleCancel = () => { + navigate('/llm-connections'); + }; + + return( +
    +
    +
    + + + +
    {t('llmConnectionForm.createConnection.title') || 'Create LLM Connection'}
    +
    +
    + {}} + /> +
    + + ) +} + +export default CreateLLMConnection; \ No newline at end of file diff --git a/GUI/src/pages/LLMConnections/LLMConnections.scss b/GUI/src/pages/LLMConnections/LLMConnections.scss new file mode 100644 index 0000000..ff55946 --- /dev/null +++ b/GUI/src/pages/LLMConnections/LLMConnections.scss @@ -0,0 +1,172 @@ +.grey-card { + border: 1px solid #a6a8b1; + border-radius: 5px; + margin-bottom: 10px; + display: flex; + gap: 20px; + align-items: center; + background-color: #f9f9f9; + padding: 25px; +} + +.blue-card { + border-radius: 10px; + margin-bottom: 10px; + display: flex; + gap: 20px; + align-items: center; + background-color: #d7edff; + padding: 25px; + margin-top: 20px; +} + +body { + font-family: Arial, sans-serif; + background-color: #f4f4f4; + margin: 0; + padding: 20px; +} + +@keyframes scaleIn { + 0% { + transform: scale(1); + opacity: 0; + } + + 100% { + transform: scale(1.02); + opacity: 1; + } +} + +.featured-content { + background-color: hsl(40, 100%, 96%); + border: 2px solid #f39c12; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + border-radius: 10px; + padding: 10px 20px; + margin: 20px auto; + transform: scale(1.02); + transition: transform 0.3s, box-shadow 0.3s; + animation: scaleIn 0.5s ease-out; +} + +.mt-30 { + margin-top: 30px; +} + +.m-30-0 { + margin: 30px 0px; +} + +.models-filter-div { + display: flex; + flex-wrap: wrap; + gap: 16px; + width: 100%; +} + +.filter-buttons { + display: flex; + gap: 16px; +} + +.data-model-buttons { + align-items: end; + gap: 10px; + justify-content: end; + margin: 25px -16px -16px; + padding: 20px 64px; + background-color: white; +} + +.metadata-card { + justify-content: center; + text-align: center; + background-color: #FFE8E9; + color: #D73E3E; + border-radius: .3rem; + padding: 2rem; + border: 1px solid #D73E3E; + margin-bottom: 2rem; +} + +.search-panel { + width: 100%; + margin-bottom: 20px; +} + +.models-filter-div { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 16px; + width: 100%; + + @media (max-width: 768px) { + grid-template-columns: 1fr; + gap: 12px; + } + + @media (min-width: 769px) and (max-width: 1024px) { + grid-template-columns: repeat(2, 1fr); + } + + @media (min-width: 1025px) { + grid-template-columns: repeat(4, 1fr) auto; + } +} + +.filter-reset-button { + display: flex; + justify-content: center; + + @media (max-width: 1024px) { + justify-content: stretch; + + button { + width: fit-content; + } + } +} + +// Additional responsive utilities +@media (max-width: 768px) { + .container { + padding: 16px 12px; + } + + .title_container { + flex-direction: column; + gap: 16px; + align-items: stretch; + + .title { + text-align: center; + } + } + + .grid-container { + grid-template-columns: 1fr; + } +} + +@media (min-width: 769px) and (max-width: 1024px) { + .grid-container { + grid-template-columns: repeat(2, 1fr); + } +} + +.grid-container { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 16px; + width: 100%; + + @media (max-width: 1024px) { + grid-template-columns: repeat(2, 1fr); + } + + @media (max-width: 800px) { + grid-template-columns: repeat(1, 1fr); + } +} diff --git a/GUI/src/pages/LLMConnections/ViewLLMConnection.tsx b/GUI/src/pages/LLMConnections/ViewLLMConnection.tsx new file mode 100644 index 0000000..4ff4212 --- /dev/null +++ b/GUI/src/pages/LLMConnections/ViewLLMConnection.tsx @@ -0,0 +1,286 @@ +import { useState, useEffect } from 'react'; +import { useNavigate, useSearchParams, Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { useDialog } from 'hooks/useDialog'; +import { Button } from 'components'; +import { ButtonAppearanceTypes } from 'enums/commonEnums'; +import BackArrowButton from 'assets/BackArrowButton'; +import LLMConnectionForm, { LLMConnectionFormData } from 'components/molecules/LLMConnectionForm'; +import { getLLMConnection, updateLLMConnection, deleteLLMConnection } from 'services/llmConnections'; +import { llmConnectionsQueryKeys } from 'utils/queryKeys'; +import CircularSpinner from 'components/molecules/CircularSpinner/CircularSpinner'; + +const ViewLLMConnection = () => { + const navigate = useNavigate(); + const { t } = useTranslation(); + const { open: openDialog, close: closeDialog } = useDialog(); + const queryClient = useQueryClient(); + const [searchParams] = useSearchParams(); + const isEditing = true; + const connectionId = searchParams.get('id'); + + // Fetch connection data + const { data: connectionData, isLoading, error } = useQuery({ + queryKey: llmConnectionsQueryKeys.detail(connectionId!), + queryFn: () => getLLMConnection(connectionId!), + enabled: !!connectionId, + }); + + // Update mutation + const updateConnectionMutation = useMutation({ + mutationFn: (data: LLMConnectionFormData) => updateLLMConnection(connectionId!, data), + onSuccess: async () => { + await queryClient.invalidateQueries({ + queryKey: llmConnectionsQueryKeys.all() + }); + + openDialog({ + title: t('llmConnectionForm.viewConnection.updateSuccessTitle') || 'Connection Update Succeeded', + content:

    {t('llmConnectionForm.viewConnection.updateSuccessMessage') || 'LLM configuration updated successfully!'}

    , + footer: ( + + ), + }); + }, + onError: (error: any) => { + console.error('Error updating LLM connection:', error); + openDialog({ + title: t('llmConnectionForm.viewConnection.updateErrorTitle') || 'Connection Update Failed', + content:

    {t('llmConnectionForm.viewConnection.updateErrorMessage') || 'Failed to update LLM connection. Please try again.'}

    , + footer: ( + + ), + }); + }, + }); + + // Delete mutation + const deleteConnectionMutation = useMutation({ + mutationFn: () => deleteLLMConnection(connectionId!), + onSuccess: async () => { + await queryClient.invalidateQueries({ + queryKey: llmConnectionsQueryKeys.all() + }); + + navigate('/llm-connections'); + + openDialog({ + title: t('llmConnectionForm.viewConnection.deleteSuccessTitle') || 'Connection Deletion Succeeded', + content:

    {t('llmConnectionForm.viewConnection.deleteSuccessMessage') || 'LLM connection deleted successfully!'}

    , + footer: ( + + ), + }); + }, + onError: (error: any) => { + console.error('Error deleting LLM connection:', error); + openDialog({ + title: t('llmConnectionForm.viewConnection.deleteErrorTitle') || 'Error', + content:

    {error?.message || t('llmConnectionForm.viewConnection.deleteErrorMessage') || 'Failed to delete LLM connection. Please try again.'}

    , + footer: ( + + ), + }); + }, + }); + + const handleSubmit = async (data: LLMConnectionFormData) => { + const isCurrentlyProduction = connectionData?.environment === 'production'; + const isChangingToTesting = data.deploymentEnvironment === 'testing'; + + if (isCurrentlyProduction && isChangingToTesting) { + openDialog({ + title: t('llmConnectionForm.viewConnection.confirmEnvironmentChangeTitle') || 'Confirm Production Environment Change', + content: ( +
    +

    {t('llmConnectionForm.viewConnection.confirmEnvironmentChangeMessage') || 'You are about to change a production connection to testing environment.'}

    +

    {t('llmConnectionForm.viewConnection.confirmEnvironmentChangeWarning') || 'This will affect the current production setup. Are you sure you want to proceed?'}

    +
    + ), + footer: ( +
    + + +
    + ), + }); + } else { + updateConnectionMutation.mutate(data); + } + }; + + const handleCancel = () => { + navigate('/llm-connections'); + }; + + + + const handleDelete = () => { + const isProductionConnection = connectionData?.environment === 'production'; + + if (isProductionConnection) { + openDialog({ + title: t('llmConnectionForm.viewConnection.cannotDeleteProductionTitle') || 'Cannot Delete Production Connection', + content: ( +
    +

    {t('llmConnectionForm.viewConnection.cannotDeleteProductionMessage') || 'This LLM connection is currently set as the production connection and cannot be deleted.'}

    +

    {t('llmConnectionForm.viewConnection.cannotDeleteProductionInstructions') || 'To delete this connection, please ensure another connection is set as the production connection.'}

    +
    + ), + footer: ( + + ), + }); + } else { + openDialog({ + title: t('llmConnectionForm.viewConnection.confirmDeleteTitle') || 'Confirm Delete', + content:

    {t('llmConnectionForm.viewConnection.confirmDeleteMessage') || 'Are you sure you want to delete this LLM connection? This action cannot be undone.'}

    , + footer: ( +
    + + +
    + ), + }); + } + }; + + if (isLoading) { + return ( +
    + +
    + ); + } + + if (error || !connectionData) { + return ( +
    +
    +
    + + + +
    {t('llmConnectionForm.viewConnection.connectionNotFoundTitle') || 'Connection Not Found'}
    +
    +
    +

    {t('llmConnectionForm.viewConnection.connectionNotFoundMessage') || 'The requested LLM connection could not be found.'}

    +
    + ); + } + + // Convert connection data to form format + const formData: LLMConnectionFormData = { + connectionName: connectionData.connectionName, + llmPlatform: connectionData.llmPlatform, + llmModel: connectionData.llmModel, + embeddingModelPlatform: connectionData.embeddingPlatform, + embeddingModel: connectionData.embeddingModel, + monthlyBudget: connectionData.monthlyBudget.toString(), + warnBudget: connectionData.warnBudgetThreshold.toString(), + stopBudget: connectionData.disconnectOnBudgetExceed ? connectionData.stopBudgetThreshold.toString() : '0', + disconnectOnBudgetExceed: connectionData.disconnectOnBudgetExceed, + deploymentEnvironment: connectionData.environment, + // Azure credentials (don't show sensitive data, but include structure) + deploymentName: connectionData.deploymentName || '', + targetUri: connectionData.targetUri || '', + apiKey: connectionData.apiKey || '', // Don't show API keys + // AWS Bedrock credentials (don't show sensitive data, but include structure) + secretKey: connectionData.secretKey || '', // Don't show API keys + accessKey: connectionData.accessKey || '', // Don't show API keys + // Embedding model credentials (don't show sensitive data, but include structure) + embeddingModelApiKey: connectionData.embeddingModelApiKey || '', // Don't show API keys + // Embedding AWS Bedrock credentials + embeddingAccessKey: connectionData.embeddingAccessKey || '', + embeddingSecretKey: connectionData.embeddingSecretKey || '', + // Embedding Azure credentials + embeddingDeploymentName: connectionData.embeddingDeploymentName || '', + embeddingTargetUri: connectionData.embeddingTargetUri || '', + embeddingAzureApiKey: connectionData.embeddingAzureApiKey || '', + }; + + return ( +
    +
    +
    + + + +
    + {connectionData?.connectionName && ` ${connectionData.connectionName}`} +
    +
    + +
    + + +
    + ); +}; + +export default ViewLLMConnection; \ No newline at end of file diff --git a/GUI/src/pages/LLMConnections/index.tsx b/GUI/src/pages/LLMConnections/index.tsx new file mode 100644 index 0000000..2484a82 --- /dev/null +++ b/GUI/src/pages/LLMConnections/index.tsx @@ -0,0 +1,312 @@ +import { FC, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, FormSelect } from 'components'; +import Pagination from 'components/molecules/Pagination'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { formattedArray } from 'utils/commonUtils'; +import DataModelCard from 'components/molecules/LLMConnectionCard'; +import CircularSpinner from 'components/molecules/CircularSpinner/CircularSpinner'; +import { ButtonAppearanceTypes } from 'enums/commonEnums'; +import NoDataView from 'components/molecules/NoDataView'; +import BudgetBanner from 'components/molecules/BudgetBanner'; +import './LLMConnections.scss'; +import { platforms, trainingStatuses } from 'config/dataModelsConfig'; +import LLMConnectionCard from 'components/molecules/LLMConnectionCard'; +import { fetchLLMConnectionsPaginated, LLMConnectionFilters, LLMConnection, getProductionConnection, ProductionConnectionFilters } from 'services/llmConnections'; +import { llmConnectionsQueryKeys } from 'utils/queryKeys'; + +const LLMConnections: FC = () => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + + const [pageIndex, setPageIndex] = useState(1); + const [filters, setFilters] = useState({ + pageNumber: 1, + pageSize: 10, + sortBy: 'created_at', + sortOrder: 'desc', + }); + + // Fetch LLM connections using TanStack Query with new paginated endpoint + const { data: connectionsResponse, isLoading: isModelDataLoading, error } = useQuery({ + queryKey: llmConnectionsQueryKeys.paginatedList(filters), + queryFn: () => fetchLLMConnectionsPaginated(filters), + }); + + // Fetch production connection separately with potential filters + const [productionFilters, setProductionFilters] = useState({ + sortBy: 'created_at', + sortOrder: 'desc', + llmPlatform: '', + llmModel: '', + }); + + const { data: productionConnection, isLoading: isProductionLoading } = useQuery({ + queryKey: llmConnectionsQueryKeys.production(productionFilters), + queryFn: () => getProductionConnection(productionFilters), + }); + + + const llmConnections = connectionsResponse; + const totalPages = connectionsResponse?.[0]?.totalPages || 1; + + // Update filters when pageIndex changes + useEffect(() => { + setFilters(prev => ({ ...prev, pageNumber: pageIndex })); + }, [pageIndex]); + + // Sync production filters with main filters on component mount + useEffect(() => { + setProductionFilters(prev => ({ + ...prev, + llmPlatform: filters.llmPlatform || '', + llmModel: filters.llmModel || '', + sortBy: filters.sortBy || 'created_at', + sortOrder: filters.sortOrder || 'desc', + })); + }, [filters.llmPlatform, filters.llmModel, filters.sortBy, filters.sortOrder]); + + const handleFilterChange = ( + name: string, + value: string | number | undefined | { name: string; id: string } + ) => { + let filterUpdate: Partial = {}; + let productionFilterUpdate: Partial = {}; + + if (name === 'sorting') { + // Handle sorting format - no conversion needed, use snake_case directly + const sortingValue = value as string; + const [sortBy, sortOrder] = sortingValue.split(' '); + + filterUpdate = { + sortBy: sortBy, + sortOrder: sortOrder as 'asc' | 'desc' + }; + + productionFilterUpdate = { + sortBy: sortBy, + sortOrder: sortOrder as 'asc' | 'desc' + }; + } else { + filterUpdate = { [name]: value }; + + // Update production filters for relevant fields + if (name === 'llmPlatform' || name === 'llmModel') { + productionFilterUpdate = { [name]: value as string }; + } + } + + setFilters((prevFilters) => ({ + ...prevFilters, + ...filterUpdate, + })); + + // Update production filters if relevant + if (Object.keys(productionFilterUpdate).length > 0) { + setProductionFilters((prevFilters) => ({ + ...prevFilters, + ...productionFilterUpdate, + })); + } + + // Reset to first page when filters change + if (name !== 'pageNumber') { + setPageIndex(1); + } + }; + + // Platform filter options + const platformOptions = [ + { label: t('dataModels.filters.allPlatforms'), value: 'all' }, + { label: t('dataModels.platforms.azure'), value: 'azure' }, + { label: t('dataModels.platforms.aws'), value: 'aws' }, + ]; + + // LLM Model filter options - these would ideally come from an API + const llmModelOptions = [ + { label: t('dataModels.filters.allModels'), value: 'all' }, + { label: t('dataModels.models.gpt4Mini'), value: 'gpt-4o-mini' }, + { label: t('dataModels.models.gpt4o'), value: 'gpt-4o' }, + { label: t('dataModels.models.claude35Sonnet'), value: 'anthropic-claude-3.5-sonnet' }, + { label: t('dataModels.models.claude37Sonnet'), value: 'anthropic-claude-3.7-sonnet' }, + ]; + + // Environment filter options + const environmentOptions = [ + { label: t('dataModels.filters.allEnvironments'), value: 'all' }, + { label: t('dataModels.environments.testing'), value: 'testing' }, + { label: t('dataModels.environments.production'), value: 'production' }, + ]; + + // Sort options - using snake_case format for backend + const sortOptions = [ + { label: t('dataModels.sortOptions.createdDateNewest'), value: 'created_at desc' }, + { label: t('dataModels.sortOptions.createdDateOldest'), value: 'created_at asc' }, + { label: t('dataModels.sortOptions.platformAZ'), value: 'llm_platform asc' }, + { label: t('dataModels.sortOptions.platformZA'), value: 'llm_platform desc' }, + { label: t('dataModels.sortOptions.modelAZ'), value: 'llm_model asc' }, + { label: t('dataModels.sortOptions.modelZA'), value: 'llm_model desc' }, + { label: t('dataModels.sortOptions.budgetHighToLow'), value: 'monthly_budget desc' }, + { label: t('dataModels.sortOptions.budgetLowToHigh'), value: 'monthly_budget asc' }, + ]; + + const currentSorting = `${filters.sortBy || 'created_at'} ${filters.sortOrder || 'desc'}`; + + // Use production connection as featured connection + const otherConnections = llmConnections || []; + + return ( +
    +
    + {!isModelDataLoading && !isProductionLoading ? ( +
    +
    +
    +
    {t('dataModels.dataModels')}
    + +
    +
    +
    + + handleFilterChange('llmPlatform', selection?.value === 'all' ? '' : selection?.value) + } + defaultValue={filters?.llmPlatform || 'all'} + /> + + handleFilterChange('llmModel', selection?.value === 'all' ? '' : selection?.value) + } + defaultValue={filters?.llmModel || 'all'} + /> + + handleFilterChange('environment', selection?.value === 'all' ? '' : selection?.value) + } + defaultValue={filters?.environment || 'all'} + /> + + + handleFilterChange('sorting', selection?.value) + } + defaultValue={currentSorting} + /> + +
    + +
    +
    +
    + + {productionConnection && filters?.environment !== "testing" && ( +
    +

    {t('dataModels.productionConnections')}

    +
    + +
    +
    + )} + + {otherConnections?.length > 0 ? ( +
    +

    {t('dataModels.otherConnections')}

    +
    + {otherConnections?.map((llmConnection: LLMConnection) => { + return ( + + ); + })} +
    +
    + ) : !productionConnection ? ( + + ) : null} + + {(error as any) && ( +
    +

    Error loading LLM connections. Please try again.

    +
    + )} +
    + 1} + canNextPage={pageIndex < totalPages} + onPageChange={setPageIndex} + /> +
    + ) : ( + + )} +
    +
    + ); +}; + +export default LLMConnections; diff --git a/GUI/src/pages/LoadingScreen/LoadingScreen.scss b/GUI/src/pages/LoadingScreen/LoadingScreen.scss new file mode 100644 index 0000000..c45e573 --- /dev/null +++ b/GUI/src/pages/LoadingScreen/LoadingScreen.scss @@ -0,0 +1,20 @@ +/* Loader container */ +.loader { + position: fixed; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + border: 8px solid #f3f3f3; /* Light grey */ + border-top: 8px solid #3498db; /* Blue */ + border-radius: 50%; + width: 60px; + height: 60px; + animation: spin 1.5s linear infinite; + } + + /* Spin animation */ + @keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } + \ No newline at end of file diff --git a/GUI/src/pages/LoadingScreen/LoadingScreen.tsx b/GUI/src/pages/LoadingScreen/LoadingScreen.tsx new file mode 100644 index 0000000..3f8add9 --- /dev/null +++ b/GUI/src/pages/LoadingScreen/LoadingScreen.tsx @@ -0,0 +1,12 @@ +import { FC } from 'react'; +import './LoadingScreen.scss' + +const LoadingScreen: FC = () => { + return ( +
    +
    +
    + ); +}; + +export default LoadingScreen; \ No newline at end of file diff --git a/GUI/src/pages/TestModel/TestLLM.scss b/GUI/src/pages/TestModel/TestLLM.scss new file mode 100644 index 0000000..833690d --- /dev/null +++ b/GUI/src/pages/TestModel/TestLLM.scss @@ -0,0 +1,210 @@ +.testModalFormTextArea { + margin-top: 30px; +} + +.testModalClassifyButton { + text-align: right; + margin-top: 20px; +} + +.llm-connection-section { + width: 50%; +} + +.llm-connection-controls { + display: flex; + gap: 1rem; + align-items: center; +} + +.inference-results-container { + max-width: 100%; + background-color: #d7efff; + padding: 20px; + border-radius: 8px; + margin-top: 20px; + + .result-item { + margin-bottom: 15px; + + strong { + color: #333; + } + } + + .response-content { + margin-top: 8px; + padding: 12px; + background-color: #f5f5f5; + border-radius: 4px; + white-space: pre-wrap; + line-height: 1.5; + color: #555; + } + + .context-section { + margin-top: 20px; + + .context-list { + display: flex; + flex-direction: column; + gap: 12px; + margin-top: 8px; + } + + .context-item { + padding: 12px; + background-color: #ffffff; + border: 1px solid #e0e0e0; + border-radius: 6px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + + .context-rank { + margin-bottom: 8px; + padding-bottom: 4px; + border-bottom: 1px solid #f0f0f0; + + strong { + color: #2563eb; + font-size: 0.875rem; + font-weight: 600; + } + } + + .context-content { + color: #374151; + line-height: 1.5; + font-size: 0.9rem; + white-space: pre-wrap; + } + } + } +} + +.testModalList { + list-style: disc; + margin-left: 30px; +} + +.mt-20 { + margin-top: 20px; +} + +.classification-results { + margin-top: 1rem; + padding: 1rem; + border: 1px solid #e0e0e0; + border-radius: 8px; + background-color: #f9f9f9; + + h3 { + margin: 0 0 1rem 0; + color: #333; + } + + h4 { + margin: 0 0 0.75rem 0; + color: #555; + font-size: 1rem; + } + + .results-container { + display: flex; + flex-direction: column; + gap: 1.5rem; + } + + .top-prediction { + .prediction-card { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem; + border-radius: 8px; + background-color: #e8f5e8; + border: 2px solid #4caf50; + + .agency-name { + font-weight: 600; + color: #2e7d32; + font-size: 1.1rem; + } + + .confidence-score { + font-weight: 700; + color: #2e7d32; + font-size: 1.2rem; + } + } + } + + .predictions-list { + display: flex; + flex-direction: column; + gap: 0.75rem; + + .prediction-item { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.75rem; + background-color: white; + border-radius: 6px; + border: 1px solid #ddd; + + &.highest { + border-color: #4caf50; + background-color: #f8fff8; + } + + .rank { + font-weight: 600; + color: #666; + min-width: 2rem; + } + + .agency-info { + flex: 1; + display: flex; + flex-direction: column; + gap: 0.25rem; + + .agency-name { + font-weight: 500; + color: #333; + } + + .confidence-bar-container { + width: 100%; + height: 4px; + background-color: #e0e0e0; + border-radius: 2px; + overflow: hidden; + + .confidence-bar { + height: 100%; + background-color: #4caf50; + transition: width 0.3s ease; + } + } + } + + .confidence-percentage { + font-weight: 600; + color: #555; + min-width: 4rem; + text-align: right; + } + } + } +} + +.classification-error { + margin-top: 1rem; + padding: 1rem; + background-color: #ffebee; + border: 1px solid #f44336; + border-radius: 6px; + color: #c62828; + text-align: center; +} \ No newline at end of file diff --git a/GUI/src/pages/TestModel/index.tsx b/GUI/src/pages/TestModel/index.tsx new file mode 100644 index 0000000..b6e66e7 --- /dev/null +++ b/GUI/src/pages/TestModel/index.tsx @@ -0,0 +1,178 @@ +import { useMutation, useQuery } from '@tanstack/react-query'; +import { Button, FormSelect, FormTextarea, Collapsible } from 'components'; +import CircularSpinner from 'components/molecules/CircularSpinner/CircularSpinner'; +import { FC, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import './TestLLM.scss'; +import { useDialog } from 'hooks/useDialog'; +import { fetchLLMConnectionsPaginated, LegacyLLMConnectionFilters } from 'services/llmConnections'; +import { viewInferenceResult, InferenceRequest, InferenceResponse } from 'services/inference'; +import { llmConnectionsQueryKeys } from 'utils/queryKeys'; +import { ButtonAppearanceTypes } from 'enums/commonEnums'; + +const TestLLM: FC = () => { + const { t } = useTranslation(); + const { open: openDialog, close: closeDialog } = useDialog(); + const [inferenceResult, setInferenceResult] = useState(null); + const [testLLM, setTestLLM] = useState({ + connectionId: null, + text: '', + }); + + // Sort context by rank + const sortedContext = inferenceResult?.chunks?.toSorted((a, b) => a.rank - b.rank) ?? []; + + // Fetch LLM connections for dropdown - using the working legacy endpoint for now + const { data: connections, isLoading: isLoadingConnections } = useQuery({ + queryKey: llmConnectionsQueryKeys.list({ + page: 1, + pageSize: 100, // Get all connections for dropdown + sorting: 'created_at desc', + }), + queryFn: () => fetchLLMConnectionsPaginated({ + pageNumber: 1, + pageSize: 100, + sortBy: 'created_at desc', + }), + }); + + // Transform connections data for dropdown + const connectionOptions = connections?.map((connection: any) => ({ + label: `${connection.llmPlatform} - ${connection.llmModel} (${connection.environment})`, + value: connection.id, + })) || []; + + // Inference mutation + const inferenceMutation = useMutation({ + mutationFn: (request: InferenceRequest) => viewInferenceResult(request), + onSuccess: (data: InferenceResponse) => { + setInferenceResult(data?.response); + }, + onError: (error: any) => { + console.error('Error getting inference result:', error); + openDialog({ + title: t('testModels.inferenceErrorTitle') || 'Inference Error', + content:

    {t('testModels.inferenceErrorMessage') || 'Failed to get inference result. Please try again.'}

    , + footer: ( + + ), + }); + }, + }); + + const handleSend = () => { + if (testLLM.connectionId && testLLM.text) { + inferenceMutation.mutate({ + llmConnectionId: Number(testLLM.connectionId), + message: testLLM.text, + }); + } + }; + + const handleChange = (key: string, value: string | number) => { + setTestLLM((prev) => ({ + ...prev, + [key]: value, + })); + }; + + return ( +
    + {isLoadingConnections ? ( + + ) : ( +
    +
    +
    {t('testModels.title') || 'Test LLM'}
    +
    +
    +

    {t('testModels.llmConnectionLabel') || 'LLM Connection'}

    +
    + + { + handleChange('connectionId', selection?.value as string); + }} + value={testLLM?.connectionId === null ? t('testModels.connectionNotExist') || 'Connection does not exist' : undefined} + defaultValue={testLLM?.connectionId ?? undefined} + /> +
    +
    + +
    +

    {t('testModels.classifyTextLabel') || 'Enter text to test'}

    + handleChange('text', e.target.value)} + showMaxLength={true} + /> +
    +
    + +
    + + {/* Inference Result */} + + {inferenceResult && !inferenceMutation.isLoading && ( +
    +
    + Response: +
    + {inferenceResult.content} +
    +
    + + {/* Context Section */} + { + sortedContext && sortedContext?.length > 0 && ( +
    + +
    + {sortedContext?.map((contextItem, index) => ( +
    +
    + Rank {contextItem.rank} +
    +
    + {contextItem.chunkRetrieved} +
    +
    + ))} +
    +
    +
    + ) + } + +
    + )} + + {/* Error State */} + {inferenceMutation.isError && ( +
    +

    {t('testModels.classificationFailed') || 'Inference failed. Please try again.'}

    +
    + )} +
    + )} +
    + ); +}; + +export default TestLLM; \ No newline at end of file diff --git a/GUI/src/pages/TestProductionLLM/TestProductionLLM.scss b/GUI/src/pages/TestProductionLLM/TestProductionLLM.scss new file mode 100644 index 0000000..1bd8e0f --- /dev/null +++ b/GUI/src/pages/TestProductionLLM/TestProductionLLM.scss @@ -0,0 +1,191 @@ +.test-production-llm { + max-width: 1200px; + margin: 0 auto; + padding: 2rem; + + &__header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; + padding-bottom: 1rem; + border-bottom: 2px solid #e0e0e0; + + h1 { + margin: 0; + color: #333; + font-size: 2rem; + } + } + + &__chat-container { + height: 70vh; + display: flex; + flex-direction: column; + border: 1px solid #e0e0e0; + border-radius: 12px; + background-color: #fff; + overflow: hidden; + } + + &__messages { + flex: 1; + overflow-y: auto; + padding: 1rem; + background-color: #f8f9fa; + display: flex; + flex-direction: column; + gap: 1rem; + } + + &__welcome { + text-align: center; + color: #666; + font-size: 1.1rem; + margin: auto; + + p { + margin: 0.5rem 0; + + &:first-child { + font-weight: 600; + color: #333; + } + } + } + + &__message { + max-width: 70%; + + &--user { + align-self: flex-end; + + .test-production-llm__message-content { + background-color: #005aa3; + color: white; + border-radius: 18px 18px 4px 18px; + } + } + + &--bot { + align-self: flex-start; + + .test-production-llm__message-content { + background-color: white; + color: #333; + border: 1px solid #e0e0e0; + border-radius: 18px 18px 18px 4px; + } + } + } + + &__message-content { + padding: 0.75rem 1rem; + word-wrap: break-word; + line-height: 1.4; + font-size: 0.95rem; + } + + &__message-timestamp { + font-size: 0.75rem; + color: #888; + margin-top: 0.25rem; + text-align: right; + + .test-production-llm__message--user & { + text-align: right; + } + + .test-production-llm__message--bot & { + text-align: left; + } + } + + &__typing { + display: flex; + gap: 4px; + + span { + width: 6px; + height: 6px; + background-color: #666; + border-radius: 50%; + animation: typing 1.4s infinite ease-in-out; + + &:nth-child(1) { + animation-delay: -0.32s; + } + + &:nth-child(2) { + animation-delay: -0.16s; + } + } + } + + &__input-area { + display: flex; + padding: 1rem; + background-color: white; + border-top: 1px solid #e0e0e0; + gap: 1rem; + align-items: flex-end; + + .form-textarea { + flex: 1; + } + } + + &__send-button { + min-width: 100px; + height: fit-content; + } +} + +@keyframes typing { + 0%, 80%, 100% { + transform: scale(0); + } + 40% { + transform: scale(1); + } +} + +// Responsive design +@media (max-width: 768px) { + .test-production-llm { + padding: 1rem; + + &__header { + flex-direction: column; + gap: 1rem; + align-items: stretch; + + h1 { + font-size: 1.5rem; + text-align: center; + } + } + + &__chat-container { + height: 60vh; + } + + &__message { + max-width: 85%; + } + + &__input-area { + flex-direction: column; + gap: 0.5rem; + + .form-textarea { + order: 1; + } + } + + &__send-button { + order: 2; + width: 100%; + } + } +} diff --git a/GUI/src/pages/TestProductionLLM/index.tsx b/GUI/src/pages/TestProductionLLM/index.tsx new file mode 100644 index 0000000..a9c1493 --- /dev/null +++ b/GUI/src/pages/TestProductionLLM/index.tsx @@ -0,0 +1,247 @@ +import { FC, useState, useRef, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, FormTextarea, Section } from 'components'; +import { productionInference, ProductionInferenceRequest } from 'services/inference'; +import { useToast } from 'hooks/useToast'; +import './TestProductionLLM.scss'; + +interface Message { + id: string; + content: string; + isUser: boolean; + timestamp: string; +} + +const TestProductionLLM: FC = () => { + const { t } = useTranslation(); + const toast = useToast(); + const [message, setMessage] = useState(''); + const [messages, setMessages] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const messagesEndRef = useRef(null); + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages]); + + const handleSendMessage = async () => { + if (!message.trim()) { + toast.open({ + type: 'warning', + title: t('warningTitle'), + message: t('emptyMessageWarning'), + }); + return; + } + + const userMessage: Message = { + id: `user-${Date.now()}`, + content: message.trim(), + isUser: true, + timestamp: new Date().toISOString(), + }; + + // Add user message to chat + setMessages(prev => [...prev, userMessage]); + setMessage(''); + setIsLoading(true); + + try { + // Hardcoded values as requested + const request: ProductionInferenceRequest = { + chatId: 'test-chat-001', + message: userMessage.content, + authorId: 'test-author-001', + conversationHistory: messages.map(msg => ({ + authorRole: msg.isUser ? 'user' : 'bot', + message: msg.content, + timestamp: msg.timestamp, + })), + url: 'https://test-url.example.com', + }; + + let response; + let attemptCount = 0; + const maxAttempts = 2; + + // Retry logic + while (attemptCount < maxAttempts) { + try { + attemptCount++; + console.log(`Production Inference Attempt ${attemptCount}/${maxAttempts}`); + response = await productionInference(request); + + // If we get a successful response, break out of retry loop + if (!response.status || response.status < 400) { + break; + } + + // If first attempt failed with error status, retry once more + if (attemptCount < maxAttempts && response.status >= 400) { + console.log('Retrying due to error status...'); + continue; + } + } catch (err) { + // If first attempt threw an error, retry once more + if (attemptCount < maxAttempts) { + console.log('Retrying due to exception...'); + continue; + } + throw err; // Re-throw on final attempt + } + } + + console.log('Production Inference Response:', response); + + // Create bot response message + let botContent = ''; + let botMessageType: 'success' | 'error' = 'success'; + + if (response.status && response.status >= 400) { + // Error response + botContent = response.content || 'An error occurred while processing your request.'; + botMessageType = 'error'; + } else { + // Success response + botContent = response?.response?.content || 'Response received successfully.'; + + if (response.questionOutOfLlmScope) { + botContent += ' (Note: This question appears to be outside the LLM scope)'; + } + } + + const botMessage: Message = { + id: `bot-${Date.now()}`, + content: botContent, + isUser: false, + timestamp: new Date().toISOString(), + }; + + setMessages(prev => [...prev, botMessage]); + + // Show toast notification + // toast.open({ + // type: botMessageType, + // title: t('errorOccurred'), + // message: t('errorMessage'), + // }); + + } catch (error) { + console.error('Error sending message:', error); + + const errorMessage: Message = { + id: `error-${Date.now()}`, + content: 'Failed to send message. Please check your connection and try again.', + isUser: false, + timestamp: new Date().toISOString(), + }; + + setMessages(prev => [...prev, errorMessage]); + + toast.open({ + type: 'error', + title: 'Connection Error', + message: 'Unable to connect to the production LLM service.', + }); + } finally { + setIsLoading(false); + } + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + handleSendMessage(); + } + }; + + const clearChat = () => { + setMessages([]); + toast.open({ + type: 'info', + title: 'Chat Cleared', + message: 'All messages have been cleared.', + }); + }; + + return ( +
    +
    +
    +

    {t('Test Production LLM')}

    + +
    + +
    +
    + {messages.length === 0 && ( +
    +

    Welcome to Production LLM Testing

    +

    Start a conversation by typing a message below.

    +
    + )} + + {messages.map((msg) => ( +
    +
    + {msg.content} +
    +
    + {new Date(msg.timestamp).toLocaleTimeString()} +
    +
    + ))} + + {isLoading && ( +
    +
    +
    + + + +
    +
    +
    + )} + +
    +
    + +
    + setMessage(e.target.value)} + onKeyDown={handleKeyPress} + placeholder="Type your message here... (Press Enter to send, Shift+Enter for new line)" + hideLabel + maxRows={4} + disabled={isLoading} + /> + +
    +
    +
    +
    + ); +}; + +export default TestProductionLLM; \ No newline at end of file diff --git a/GUI/src/pages/UserManagement/SettingsUsers.scss b/GUI/src/pages/UserManagement/SettingsUsers.scss new file mode 100644 index 0000000..37e5f63 --- /dev/null +++ b/GUI/src/pages/UserManagement/SettingsUsers.scss @@ -0,0 +1,48 @@ +@import 'src/styles/tools/spacing'; +@import 'src/styles/tools/color'; +@import 'src/styles/settings/variables/other'; +@import 'src/styles/settings/variables/typography'; + +.multiSelect { + $self: &; + display: flex; + align-items: center; + gap: get-spacing(paldiski); + width: 100%; + &::placeholder { + color: get-color(black-coral-6); + font-size: small; + } + + &__label { + flex: 0 0 185px; + font-size: $veera-font-size-100; + line-height: 24px; + } + + + &__wrapper { + width: 390px; + flex: 1; + display: block; + flex-direction: column; + gap: 7px; + position: relative; + border: 0.15px solid get-color(black-coral-6); + border-radius: $veera-radius-s; + } +} + +.footer-button-wrapper { + display: flex; + gap: 10px; +} + +.button-wrapper { + display: flex; + gap: 10px; +} + +.error-span { + color: get-color(jasper-10); +} \ No newline at end of file diff --git a/GUI/src/pages/UserManagement/UserManagement.scss b/GUI/src/pages/UserManagement/UserManagement.scss new file mode 100644 index 0000000..969be2a --- /dev/null +++ b/GUI/src/pages/UserManagement/UserManagement.scss @@ -0,0 +1,28 @@ + +.button { + background-color: #007bff; + padding: 10px 20px; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 1rem; +} + +.button:hover { + background-color: #0056b3; +} + +.form-group { + margin-bottom: 20px; +} + +.table-header { + display: flex; + width: 100%; + justify-content: end; +} + +.action-button-container { + display: flex; + gap: 10px; +} diff --git a/GUI/src/pages/UserManagement/UserModal.tsx b/GUI/src/pages/UserManagement/UserModal.tsx new file mode 100644 index 0000000..345ee90 --- /dev/null +++ b/GUI/src/pages/UserManagement/UserModal.tsx @@ -0,0 +1,298 @@ +import { useForm, Controller, useWatch } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { AxiosError } from 'axios'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { Button, Dialog, FormInput, Track } from 'components'; +import { User, UserDTO } from 'types/user'; +import { checkIfUserExists, createUser, editUser } from 'services/users'; +import { useToast } from 'hooks/useToast'; +import Select, { components } from 'react-select'; +import './SettingsUsers.scss'; +import { FC, useMemo, useState } from 'react'; +import { ROLES } from 'enums/roles'; +import { userManagementQueryKeys } from 'utils/queryKeys'; +import { ButtonAppearanceTypes, ToastTypes } from 'enums/commonEnums'; +import { FaChevronDown, FaChevronUp } from 'react-icons/fa'; + +type UserModalProps = { + onClose: () => void; + user?: User; + isModalOpen?: boolean; +}; + +const DropdownIndicator = (props: any) => { + return ( + + {props.selectProps.menuIsOpen ? : } + + ); +}; + +const UserModal: FC = ({ onClose, user, isModalOpen }) => { + const { t } = useTranslation(); + const toast = useToast(); + const queryClient = useQueryClient(); + const [isValidIdentification, setIsValidIdentification] = + useState(false); + + const { + register, + control, + handleSubmit, + formState: { errors, isDirty }, + } = useForm({ + defaultValues: { + useridcode: user?.useridcode, + authorities: user?.authorities, + csaTitle: user?.csaTitle, + csaEmail: user?.csaEmail, + fullName: user?.firstName && user?.lastName ? `${user?.firstName} ${user?.lastName}` : "", + }, + }); + + const watchedValues = useWatch({ + control, + }); + + const roles = useMemo( + () => [ + { label: t('roles.ROLE_ADMINISTRATOR'), value: ROLES.ROLE_ADMINISTRATOR }, + { + label: t('roles.ROLE_MODEL_TRAINER'), + value: ROLES.ROLE_MODEL_TRAINER, + }, + ], + [t] + ); + + const userCreateMutation = useMutation({ + mutationFn: (data: UserDTO) => createUser(data), + onSuccess: async () => { + await queryClient.invalidateQueries( + userManagementQueryKeys.getAllEmployees() + ); + toast.open({ + type: ToastTypes.SUCCESS, + title: t('global.notification'), + message: t('toast.success.newUserAdded'), + }); + onClose(); + }, + onError: (error: AxiosError) => { + toast.open({ + type: ToastTypes.ERROR, + title: t('global.notificationError'), + message: error?.message ?? '', + }); + }, + }); + + const userEditMutation = useMutation({ + mutationFn: ({ + id, + userData, + }: { + id: string | number; + userData: UserDTO; + }) => editUser(id, userData), + onSuccess: async () => { + await queryClient.invalidateQueries( + userManagementQueryKeys.getAllEmployees() + ); + toast.open({ + type: ToastTypes.SUCCESS, + title: t('global.notification'), + message: t('toast.success.userUpdated'), + }); + onClose(); + }, + onError: (error: AxiosError) => { + toast.open({ + type: ToastTypes.ERROR, + title: t('global.notificationError'), + message: error?.message ?? '', + }); + }, + }); + + const checkIfUserExistsMutation = useMutation({ + mutationFn: ({ userData }: { userData: UserDTO }) => + checkIfUserExists(userData), + onSuccess: async (data) => { + if (data.response === 'true') { + setIsValidIdentification(false); + toast.open({ + type: ToastTypes.ERROR, + title: t('global.notificationError'), + message: t('userManagement.addUser.userExists'), + }); + } else { + createNewUser(); + } + }, + onError: (error: AxiosError) => { + toast.open({ + type: ToastTypes.ERROR, + title: t('global.notificationError'), + message: error?.message, + }); + }, + }); + + const createNewUser = handleSubmit((userData) => + userCreateMutation.mutate(userData) + ); + + const handleUserSubmit = handleSubmit((data) => { + if (user) userEditMutation.mutate({ id: user.useridcode, userData: data }); + else checkIfUserExistsMutation.mutate({ userData: data }); + }); + + const hasChangedFields = () => { + return ( + watchedValues.useridcode !== user?.useridcode || + watchedValues.authorities?.join(',') !== user?.authorities?.join(',') || + watchedValues !== user?.displayName || + watchedValues.csaTitle !== user?.csaTitle || + watchedValues.csaEmail !== user?.csaEmail); + }; + + return ( + + + +
    + } + > + + + {errors?.fullName && ( + {errors?.fullName?.message} + )} + + ( +
    + +
    +