DEVJHAWAR11 commited on
Commit
5b7955a
·
0 Parent(s):

sync: deploy to HuggingFace Space

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .agent/workflows/rag-engine-build.md +80 -0
  2. .dockerignore +12 -0
  3. .env.example +51 -0
  4. .github/workflows/sync-to-hf.yml +28 -0
  5. .gitignore +27 -0
  6. .pyre_configuration +19 -0
  7. .vscode/settings.json +13 -0
  8. Dockerfile +39 -0
  9. README.md +46 -0
  10. api/__init__.py +0 -0
  11. api/main.py +76 -0
  12. api/routes/__init__.py +0 -0
  13. api/routes/health.py +31 -0
  14. api/routes/ingest.py +192 -0
  15. api/routes/query.py +44 -0
  16. api/schemas.py +67 -0
  17. backend/.env.example +5 -0
  18. backend/.gitignore +2 -0
  19. backend/node_modules/.package-lock.json +1431 -0
  20. backend/node_modules/asynckit/LICENSE +21 -0
  21. backend/node_modules/asynckit/README.md +233 -0
  22. backend/node_modules/asynckit/bench.js +76 -0
  23. backend/node_modules/asynckit/index.js +6 -0
  24. backend/node_modules/asynckit/lib/abort.js +29 -0
  25. backend/node_modules/asynckit/lib/async.js +34 -0
  26. backend/node_modules/asynckit/lib/defer.js +26 -0
  27. backend/node_modules/asynckit/lib/iterate.js +75 -0
  28. backend/node_modules/asynckit/lib/readable_asynckit.js +91 -0
  29. backend/node_modules/asynckit/lib/readable_parallel.js +25 -0
  30. backend/node_modules/asynckit/lib/readable_serial.js +25 -0
  31. backend/node_modules/asynckit/lib/readable_serial_ordered.js +29 -0
  32. backend/node_modules/asynckit/lib/state.js +37 -0
  33. backend/node_modules/asynckit/lib/streamify.js +141 -0
  34. backend/node_modules/asynckit/lib/terminator.js +29 -0
  35. backend/node_modules/asynckit/package.json +63 -0
  36. backend/node_modules/asynckit/parallel.js +43 -0
  37. backend/node_modules/asynckit/serial.js +17 -0
  38. backend/node_modules/asynckit/serialOrdered.js +75 -0
  39. backend/node_modules/asynckit/stream.js +21 -0
  40. backend/node_modules/call-bind-apply-helpers/.eslintrc +17 -0
  41. backend/node_modules/call-bind-apply-helpers/.github/FUNDING.yml +12 -0
  42. backend/node_modules/call-bind-apply-helpers/.nycrc +9 -0
  43. backend/node_modules/call-bind-apply-helpers/CHANGELOG.md +30 -0
  44. backend/node_modules/call-bind-apply-helpers/LICENSE +21 -0
  45. backend/node_modules/call-bind-apply-helpers/README.md +62 -0
  46. backend/node_modules/call-bind-apply-helpers/actualApply.d.ts +1 -0
  47. backend/node_modules/call-bind-apply-helpers/actualApply.js +10 -0
  48. backend/node_modules/call-bind-apply-helpers/applyBind.d.ts +19 -0
  49. backend/node_modules/call-bind-apply-helpers/applyBind.js +10 -0
  50. backend/node_modules/call-bind-apply-helpers/functionApply.d.ts +1 -0
.agent/workflows/rag-engine-build.md ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: # RAG Engine Build Workflow — PolicyDecoder
3
+ ---
4
+
5
+ # RAG Engine Build Workflow — PolicyDecoder
6
+
7
+ ## Project Context
8
+ Python RAG engine for PolicyDecoder AI.
9
+ Folder: `rag_engine/` inside the monorepo root.
10
+ Branch: `feat/rag-engine`
11
+
12
+ ## Rules the Agent Must Follow
13
+ 1. ALL Python files go inside `rag_engine/` — never outside it.
14
+ 2. Never touch `main` branch — always stay on `feat/rag-engine`.
15
+ 3. Every new file must have a module docstring at the top.
16
+ 4. Use `pydantic-settings` for all config — never hardcode API keys.
17
+ 5. Never write frontend, backend, API routing, or deployment code.
18
+ 6. Every class must have a docstring explaining its responsibility.
19
+ 7. After creating files, always run `python -m pytest rag_engine/tests/ -v`
20
+ 8. Always use `from utils.logger import get_logger` for logging.
21
+ 9. Never commit `.env` — only `.env.example`.
22
+ 10. Commit after EVERY agent prompt task completes — not after entire phases.
23
+ One logical unit of work = one git commit. Never bundle multiple
24
+ unrelated changes into a single commit.
25
+ 11. Always run tests before committing:
26
+ `python -m pytest rag_engine/tests/ -v`
27
+ Never commit if tests are failing.
28
+ 12. Stage ONLY the files created or modified in the current task.
29
+ Never use: `git add .`
30
+ Always use: `git add <specific-files-or-folders>`
31
+ This prevents accidentally staging .env or unrelated changes.
32
+ 13. Commit message format (Conventional Commits standard):
33
+ `feat(rag): short description` ← new functionality
34
+ `fix(rag): short description` ← bug fix
35
+ `test(rag): short description` ← test files only
36
+ `chore(rag): short description` ← config, deps, non-code
37
+ `refactor(rag): short description` ← restructure, no behaviour change
38
+ `docs(rag): short description` ← README, docstrings only
39
+ 14. After every commit, push immediately:
40
+ `git push origin feat/rag-engine`
41
+ 15. Never commit these files ever:
42
+ `.env`, `__pycache__/`, `*.pyc`, `.venv/`
43
+ If you accidentally stage .env: `git reset HEAD .env`
44
+
45
+ ## Tech Stack
46
+ - Python 3.11+
47
+ - llama-parse for PDF parsing
48
+ - Supabase pgvector (via langchain-community SupabaseVectorStore) for vector storage
49
+ - LangChain + langchain-openai for retrieval
50
+ - Kimi K2.5 via Moonshot AI OpenAI-compatible API (base_url: https://api.moonshot.ai/v1)
51
+ - openai Python SDK with custom base_url for Kimi
52
+ - sentence-transformers (BAAI/bge-large-en-v1.5, 768-dim) for embeddings
53
+ LOCAL model — zero API cost, no key needed
54
+ Fallback: Jina Embeddings v3 API (jina-embeddings-v3, needs JINA_API_KEY)
55
+ - pydantic v2 + pydantic-settings for schemas
56
+ - tiktoken for token counting
57
+ - pytest for testing
58
+
59
+ ## Vector Store Notes
60
+ - Supabase pgvector is used — NOT ChromaDB
61
+ - Policy isolation is done via metadata JSONB column: metadata->>'policy_id'
62
+ - The table name is: policy_chunks
63
+ - Embedding dimension: 768 (BAAI/bge-large-en-v1.5 local default)
64
+ If switching to Jina: 1024. If switching to OpenAI: 1536.
65
+
66
+ ## LLM Notes
67
+ - Primary LLM: Kimi K2.5 via Moonshot AI
68
+ - API base: https://api.moonshot.ai/v1
69
+ - Model name: kimi-k2.5
70
+ - API is OpenAI-compatible — use ChatOpenAI from langchain-openai with custom base_url
71
+ - Fallback LLM: GPT-4o via OpenAI (same interface, just change base_url + model)
72
+
73
+ ## Phases
74
+ - Phase 1: Parsing & Chunking (ingestion/, chunking/, schemas/chunk_metadata.py)
75
+ - Phase 2: Embedding pipeline (embeddings/)
76
+ - Phase 3: Vector storage (vector_store/ using Supabase pgvector)
77
+ - Phase 4: Retrieval logic (retrieval/)
78
+ - Phase 5: Prompt system + Kimi K2.5 LLM (prompts/, llm/)
79
+ - Phase 6: End-to-end service (services/, main.py)
80
+ - Phase 7: Evaluation & tuning (tests/)
.dockerignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .venv
2
+ __pycache__
3
+ *.pyc
4
+ *.pyo
5
+ .env
6
+ .git
7
+ .gitignore
8
+ *.log
9
+ .pytest_cache
10
+ tests/
11
+ *.md
12
+ .DS_Store
.env.example ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ============================================================
2
+ # PolicyDecoder RAG Engine — Environment Variables Template
3
+ # Copy this file to .env and fill in real values
4
+ # NEVER commit .env — it is gitignored
5
+ # ============================================================
6
+
7
+ # ── LlamaParse (REQUIRED for Phase 1 PDF parsing) ───────────
8
+ # Get at: https://cloud.llamaindex.ai
9
+ LLAMA_CLOUD_API_KEY=llx-your-key-here
10
+
11
+ # ── Kimi K2.5 via Moonshot AI (REQUIRED — primary LLM) ──────
12
+ # Get at: https://platform.moonshot.ai
13
+ MOONSHOT_API_KEY=sk-your-moonshot-key-here
14
+ KIMI_BASE_URL=https://api.moonshot.ai/v1
15
+ KIMI_MODEL=kimi-k2.5
16
+
17
+ # ── Supabase (REQUIRED — vector store) ──────────────────────
18
+ # Supabase dashboard → Project Settings → API
19
+ # Use the service_role key (not anon key) for RAG engine writes
20
+ SUPABASE_URL=https://your-project.supabase.co
21
+ SUPABASE_SERVICE_KEY=your-service-role-key-here
22
+ VECTOR_TABLE_NAME=policy_chunks
23
+
24
+ # ── Embedding (DEFAULT: local, FREE, no key needed) ─────────
25
+ # Options: local | jina | cohere | openai
26
+ EMBEDDING_PROVIDER=local
27
+ EMBEDDING_MODEL=BAAI/bge-large-en-v1.5
28
+ EMBEDDING_DIMENSION=768
29
+
30
+ # ── Optional: Jina Embeddings v3 ($0.045 per 1M tokens) ─────
31
+ # Only needed if EMBEDDING_PROVIDER=jina
32
+ JINA_API_KEY=jina_your-key-here
33
+
34
+ # ── Optional: Cohere (free tier — reranker only) ─────────────
35
+ # Only needed if RERANKER_PROVIDER=cohere
36
+ COHERE_API_KEY=your-cohere-key-here
37
+
38
+ # ── Optional: OpenAI (only if EMBEDDING_PROVIDER=openai) ─────
39
+ # Not needed for default local setup
40
+ OPENAI_API_KEY=sk-your-key-here
41
+
42
+ # ── LLM Selection ────────────────────────────────────────────
43
+ LLM_PROVIDER=kimi
44
+ LLM_MODEL=kimi-k2.5
45
+
46
+ # ── Reranker ─────────────────────────────────────────────────
47
+ # Options: cross_encoder (local, free) | cohere | none
48
+ RERANKER_PROVIDER=cross_encoder
49
+
50
+ # ── Debug ─────────────────────────────────────────────────────
51
+ DEBUG=false
.github/workflows/sync-to-hf.yml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Sync to HuggingFace Space
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ sync-to-hf:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout repo
13
+ uses: actions/checkout@v3
14
+ with:
15
+ fetch-depth: 1
16
+
17
+ - name: Push to HuggingFace Space
18
+ env:
19
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
20
+ run: |
21
+ git config --global user.email "jhawardev11@gmail.com"
22
+ git config --global user.name "DEVJHAWAR11"
23
+ find . -name "*.zip" -delete
24
+ git remote add hf https://DEVJHAWAR11:${HF_TOKEN}@huggingface.co/spaces/devjhawar/policylens-rag-api
25
+ git checkout --orphan hf-deploy
26
+ git add -A
27
+ git commit -m "sync: deploy to HuggingFace Space"
28
+ git push hf hf-deploy:main --force
.gitignore ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python bytecode
2
+ __pycache__/
3
+ *.pyc
4
+
5
+ # Environment
6
+ .env
7
+ .venv/
8
+
9
+ # Parsed documents cache
10
+ parsed_docs/
11
+ .cache/
12
+
13
+ # Logs
14
+ *.log
15
+
16
+ # Testing
17
+ .pytest_cache/
18
+ .coverage
19
+
20
+ # Build artifacts
21
+ dist/
22
+ build/
23
+
24
+ # macOS
25
+ .DS_Store
26
+ rag_engine.egg-info/
27
+ *.egg-info/
.pyre_configuration ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "source_directories": [
3
+ {
4
+ "import_root": ".",
5
+ "source": "rag_engine"
6
+ }
7
+ ],
8
+ "search_path": [
9
+ ".venv/Lib/site-packages"
10
+ ],
11
+ "python_version": "3.12",
12
+ "strict": false,
13
+ "ignore_all_errors": true,
14
+ "exclude": [
15
+ ".venv",
16
+ "**/__pycache__",
17
+ "node_modules"
18
+ ]
19
+ }
.vscode/settings.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "python.defaultInterpreterPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe",
3
+ "python.terminal.activateEnvironment": true,
4
+ "python.terminal.activateEnvInCurrentTerminal": true,
5
+ "python.analysis.typeCheckingMode": "off",
6
+ "python.analysis.diagnosticMode": "off",
7
+ "python.analysis.ignore": [
8
+ "**/*"
9
+ ],
10
+ "terminal.integrated.env.windows": {
11
+ "PYTHONPATH": "${workspaceFolder}"
12
+ }
13
+ }
Dockerfile ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # System deps for torch / sentence-transformers
6
+ RUN apt-get update && apt-get install -y \
7
+ gcc \
8
+ g++ \
9
+ curl \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Copy requirements first (Docker layer caching — faster rebuilds)
13
+ COPY requirements.txt .
14
+
15
+ # Install Python deps
16
+ RUN pip install --no-cache-dir --timeout 300 --upgrade pip && \
17
+ pip install --no-cache-dir --timeout 300 -r requirements.txt
18
+
19
+ # Pre-download embedding model at BUILD time into /app/model_cache
20
+ # This path is inside WORKDIR and persists into the running container
21
+ ENV HF_HOME=/app/model_cache
22
+ ENV SENTENCE_TRANSFORMERS_HOME=/app/model_cache/sentence_transformers
23
+ RUN python -c "from sentence_transformers import SentenceTransformer; print('Downloading model...'); SentenceTransformer('BAAI/bge-large-en-v1.5', device='cpu'); print('Model cached.')"
24
+
25
+ # Copy entire project
26
+ COPY . .
27
+
28
+ # Temp dir for PDF uploads
29
+ RUN mkdir -p /tmp/policydecoder_uploads
30
+
31
+ # Expose port
32
+ EXPOSE 7860
33
+
34
+ # Health check — start-period=30s since model is pre-baked, no download needed
35
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
36
+ CMD curl -f http://localhost:7860/ || exit 1
37
+
38
+ # Start FastAPI server
39
+ CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: PolicyLens RAG API
3
+ emoji: 🔍
4
+ colorFrom: blue
5
+ colorTo: indigo
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ ---
10
+
11
+ # PolicyLens — AI Insurance Policy Decoder
12
+
13
+ AI to decode and explain complex insurance/mortgage clauses in simple, easy-to-understand terms.
14
+
15
+ ## Tech Stack
16
+
17
+ - **Frontend:** React.js, Vite, Tailwind CSS
18
+ - **Backend:** Node.js, Express.js
19
+ - **Database:** Supabase (Vector DB + Storage)
20
+ - **AI:** Kimi API (Moonshot)
21
+ - **Other:** LlamaParse (OCR), RAG (LangChain)
22
+
23
+ ## Features
24
+
25
+ 1. Upload PDF/Images (Batch Upload)
26
+ 2. Summary Cards — key coverage, deductibles, exclusions
27
+ 3. AI Chat — ask questions about your policy in plain language
28
+ 4. Chat History — revisit past Q&A per policy
29
+ 5. User Authentication — register, login, JWT-based sessions
30
+
31
+ ## API Endpoints
32
+
33
+ | Method | Endpoint | Description |
34
+ |--------|----------|-------------|
35
+ | POST | `/auth/register` | Register new user |
36
+ | POST | `/auth/login` | Login and get JWT token |
37
+ | GET | `/auth/me` | Get logged-in user info |
38
+ | POST | `/ingest/upload` | Upload policy PDF/image |
39
+ | GET | `/ingest/status/{policy_id}` | Check ingestion status |
40
+ | GET | `/ingest/summary/{policy_id}` | Get AI-generated summary |
41
+ | POST | `/query/ask` | Ask a question about a policy |
42
+ | GET | `/history/{policy_id}` | Get chat history for a policy |
43
+
44
+ ## Live API Docs
45
+
46
+ [https://devjhawar-policylens-rag-api.hf.space/docs](https://devjhawar-policylens-rag-api.hf.space/docs)
api/__init__.py ADDED
File without changes
api/main.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """PolicyDecoder RAG API — FastAPI application entry point."""
2
+
3
+ import sys
4
+ import io
5
+ sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
6
+ sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
7
+
8
+ from contextlib import asynccontextmanager
9
+ import logging
10
+
11
+ from fastapi import FastAPI
12
+ from fastapi.middleware.cors import CORSMiddleware
13
+ from fastapi.responses import JSONResponse
14
+ import uvicorn
15
+
16
+ from api.routes.query import router as query_router
17
+ from api.routes.ingest import router as ingest_router
18
+ from api.routes.health import router as health_router
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ # ------------------------------------------------------------------ #
24
+ # Lifespan — pre-load heavy components once at startup
25
+ # ------------------------------------------------------------------ #
26
+ @asynccontextmanager
27
+ async def lifespan(app: FastAPI):
28
+ """Load QueryService on startup so the first request is fast."""
29
+ from rag_engine.services.query_service import QueryService
30
+
31
+ app.state.query_service = QueryService()
32
+ logger.info("QueryService loaded and ready")
33
+ yield
34
+
35
+
36
+ # ------------------------------------------------------------------ #
37
+ # App
38
+ # ------------------------------------------------------------------ #
39
+ app = FastAPI(
40
+ title="PolicyDecoder RAG API",
41
+ description="AI-powered insurance policy Q&A engine",
42
+ version="1.0.0",
43
+ lifespan=lifespan,
44
+ )
45
+
46
+ # CORS — wide open for development
47
+ app.add_middleware(
48
+ CORSMiddleware,
49
+ allow_origins=["*"],
50
+ allow_credentials=True,
51
+ allow_methods=["*"],
52
+ allow_headers=["*"],
53
+ )
54
+
55
+
56
+ # ------------------------------------------------------------------ #
57
+ # Root endpoint — required for HF Space health check
58
+ # ------------------------------------------------------------------ #
59
+ @app.get("/")
60
+ async def root():
61
+ return JSONResponse({"status": "ok", "message": "PolicyLens RAG API is running"})
62
+
63
+
64
+ # ------------------------------------------------------------------ #
65
+ # Routers
66
+ # ------------------------------------------------------------------ #
67
+ app.include_router(query_router)
68
+ app.include_router(ingest_router)
69
+ app.include_router(health_router)
70
+
71
+
72
+ # ------------------------------------------------------------------ #
73
+ # Dev entry point
74
+ # ------------------------------------------------------------------ #
75
+ if __name__ == "__main__":
76
+ uvicorn.run("api.main:app", host="0.0.0.0", port=8000, reload=True)
api/routes/__init__.py ADDED
File without changes
api/routes/health.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Health router — quick liveness / readiness probe."""
2
+
3
+ from fastapi import APIRouter
4
+
5
+ from api.schemas import HealthResponse
6
+
7
+ import logging
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ router = APIRouter(prefix="/health", tags=["health"])
12
+
13
+
14
+ @router.get("/", response_model=HealthResponse)
15
+ async def health_check():
16
+ """Return service health including Supabase connectivity."""
17
+ from rag_engine.vector_store.store_factory import get_vector_store
18
+
19
+ try:
20
+ store = get_vector_store()
21
+ store.policy_exists("health-check-ping")
22
+ supabase_ok = True
23
+ except Exception:
24
+ supabase_ok = False
25
+
26
+ return HealthResponse(
27
+ status="ok" if supabase_ok else "degraded",
28
+ version="1.0.0",
29
+ supabase_connected=supabase_ok,
30
+ model="BAAI/bge-base-en-v1.5 + kimi-k2.5",
31
+ )
api/routes/ingest.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Ingest router — trigger PDF ingestion (background) and check status."""
2
+
3
+ import os
4
+ import shutil
5
+ import tempfile
6
+
7
+ from fastapi import APIRouter, BackgroundTasks, Form, HTTPException, UploadFile
8
+
9
+ from api.schemas import IngestRequest, IngestResponse, PolicySummaryResponse
10
+
11
+ import logging
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ router = APIRouter(prefix="/ingest", tags=["ingest"])
16
+
17
+
18
+ # ------------------------------------------------------------------ #
19
+ # Background workers
20
+ # ------------------------------------------------------------------ #
21
+ def _run_ingestion(policy_id: str, pdf_path: str, overwrite: bool) -> None:
22
+ """Run ingestion synchronously inside a background thread (URL mode)."""
23
+ from rag_engine.services.ingestion_service import IngestionService
24
+
25
+ service = IngestionService()
26
+ result = service.ingest(pdf_path, policy_id, overwrite=overwrite)
27
+ logger.info("Background ingestion complete: %s", result)
28
+
29
+ # Auto-generate summary after successful ingestion
30
+ if result.get("status") == "success":
31
+ _auto_generate_summary(policy_id)
32
+
33
+
34
+ def _run_ingestion_from_file(policy_id: str, tmp_path: str, overwrite: bool) -> None:
35
+ """Run ingestion from a temp file and always clean up afterwards."""
36
+ try:
37
+ from rag_engine.services.ingestion_service import IngestionService
38
+
39
+ service = IngestionService()
40
+ result = service.ingest(tmp_path, policy_id, overwrite=overwrite)
41
+ logger.info("File ingestion complete | policy_id=%s | result=%s", policy_id, result)
42
+
43
+ # Auto-generate summary after successful ingestion
44
+ if result.get("status") == "success":
45
+ _auto_generate_summary(policy_id)
46
+ except Exception as e:
47
+ logger.error("File ingestion failed | policy_id=%s | error=%s", policy_id, e)
48
+ finally:
49
+ if os.path.exists(tmp_path):
50
+ os.unlink(tmp_path)
51
+
52
+
53
+ def _auto_generate_summary(policy_id: str) -> None:
54
+ """Generate and store a policy summary. Failures are logged, not raised."""
55
+ try:
56
+ from rag_engine.services.summary_service import SummaryService
57
+
58
+ svc = SummaryService()
59
+ summary = svc.generate(policy_id)
60
+ if "error" not in summary:
61
+ svc.store(policy_id, summary)
62
+ logger.info("Auto-generated summary for policy_id=%s", policy_id)
63
+ else:
64
+ logger.warning("Summary generation returned error for policy_id=%s: %s", policy_id, summary)
65
+ except Exception as e:
66
+ logger.error("Auto-summary failed for policy_id=%s: %s", policy_id, e)
67
+
68
+
69
+ # ------------------------------------------------------------------ #
70
+ # POST /ingest/
71
+ # ------------------------------------------------------------------ #
72
+ @router.post("/", response_model=IngestResponse)
73
+ async def ingest_policy(body: IngestRequest, background_tasks: BackgroundTasks):
74
+ """Kick off ingestion in the background and return immediately."""
75
+ if body.pdf_url is None:
76
+ raise HTTPException(
77
+ status_code=400,
78
+ detail="pdf_url is required. File upload endpoint coming soon.",
79
+ )
80
+
81
+ background_tasks.add_task(
82
+ _run_ingestion, body.policy_id, body.pdf_url, body.overwrite
83
+ )
84
+
85
+ return IngestResponse(
86
+ status="processing",
87
+ policy_id=body.policy_id,
88
+ message="Ingestion started in background. Poll /ingest/status/{policy_id}",
89
+ )
90
+
91
+
92
+ # ------------------------------------------------------------------ #
93
+ # GET /ingest/status/{policy_id}
94
+ # ------------------------------------------------------------------ #
95
+ @router.get("/status/{policy_id}")
96
+ async def ingest_status(policy_id: str):
97
+ """Check whether a policy has been ingested and how many chunks it has."""
98
+ from rag_engine.vector_store.store_factory import get_vector_store
99
+
100
+ store = get_vector_store()
101
+ exists = store.policy_exists(policy_id)
102
+ count = store.get_policy_chunk_count(policy_id) if exists else 0
103
+
104
+ return {
105
+ "policy_id": policy_id,
106
+ "ingested": exists,
107
+ "chunk_count": count,
108
+ "status": "ready" if exists else "not_found",
109
+ }
110
+
111
+
112
+ # ------------------------------------------------------------------ #
113
+ # POST /ingest/upload (multipart file upload)
114
+ # ------------------------------------------------------------------ #
115
+ @router.post("/upload", response_model=IngestResponse)
116
+ async def ingest_upload(
117
+ file: UploadFile,
118
+ policy_id: str = Form(...),
119
+ overwrite: bool = Form(False),
120
+ background_tasks: BackgroundTasks = BackgroundTasks(),
121
+ ):
122
+ """Upload a PDF file and ingest it in the background."""
123
+ # a) Validate file type
124
+ if not file.filename or not file.filename.endswith(".pdf"):
125
+ raise HTTPException(status_code=400, detail="Only PDF files accepted")
126
+
127
+ # b) Save to temp directory
128
+ suffix = f"_{file.filename}"
129
+ with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
130
+ shutil.copyfileobj(file.file, tmp)
131
+ tmp_path = tmp.name
132
+
133
+ # c) Check if policy already ingested
134
+ from rag_engine.vector_store.store_factory import get_vector_store
135
+
136
+ store = get_vector_store()
137
+ if store.policy_exists(policy_id) and not overwrite:
138
+ os.unlink(tmp_path)
139
+ return IngestResponse(
140
+ status="skipped",
141
+ policy_id=policy_id,
142
+ message="Policy already ingested. Pass overwrite=true to re-ingest.",
143
+ )
144
+
145
+ # d) Run ingestion in background
146
+ background_tasks.add_task(_run_ingestion_from_file, policy_id, tmp_path, overwrite)
147
+
148
+ return IngestResponse(
149
+ status="processing",
150
+ policy_id=policy_id,
151
+ message=f"Ingestion started. Poll /ingest/status/{policy_id}",
152
+ )
153
+
154
+
155
+ # ------------------------------------------------------------------ #
156
+ # POST /ingest/summary/{policy_id} (on-demand summary generation)
157
+ # ------------------------------------------------------------------ #
158
+ @router.post("/summary/{policy_id}", response_model=PolicySummaryResponse)
159
+ async def generate_summary(policy_id: str):
160
+ """Generate (or re-generate) a structured policy summary on demand."""
161
+ from rag_engine.services.summary_service import SummaryService
162
+
163
+ svc = SummaryService()
164
+ summary = svc.generate(policy_id)
165
+
166
+ if "error" in summary:
167
+ raise HTTPException(status_code=404, detail=summary)
168
+
169
+ svc.store(policy_id, summary)
170
+ return PolicySummaryResponse(policy_id=policy_id, summary=summary)
171
+
172
+
173
+ # ------------------------------------------------------------------ #
174
+ # GET /ingest/summary/{policy_id} (fetch stored summary)
175
+ # ------------------------------------------------------------------ #
176
+ @router.get("/summary/{policy_id}", response_model=PolicySummaryResponse)
177
+ async def get_summary(policy_id: str):
178
+ """Retrieve a previously generated policy summary."""
179
+ from rag_engine.services.summary_service import SummaryService
180
+
181
+ svc = SummaryService()
182
+ row = svc.fetch(policy_id)
183
+
184
+ if not row:
185
+ raise HTTPException(
186
+ status_code=404,
187
+ detail=f"No summary found for policy_id={policy_id}",
188
+ )
189
+
190
+ return PolicySummaryResponse(
191
+ policy_id=row["policy_id"], summary=row["summary"]
192
+ )
api/routes/query.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Query router — answer questions against an ingested policy."""
2
+
3
+ from fastapi import APIRouter, HTTPException, Request
4
+
5
+ from api.schemas import QueryRequest, QueryResponse
6
+
7
+ import logging
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ router = APIRouter(prefix="/query", tags=["query"])
12
+
13
+
14
+ @router.post("/", response_model=QueryResponse)
15
+ async def query_policy(body: QueryRequest, request: Request):
16
+ """Run the RAG pipeline for a single policy question."""
17
+ query_service = request.app.state.query_service
18
+
19
+ try:
20
+ result = query_service.query(
21
+ question=body.question,
22
+ policy_id=body.policy_id,
23
+ k=body.k,
24
+ )
25
+ except Exception as exc:
26
+ logger.exception("QueryService.query failed")
27
+ raise HTTPException(status_code=500, detail=str(exc))
28
+
29
+ if not result:
30
+ raise HTTPException(status_code=500, detail="Empty result from QueryService")
31
+
32
+ logger.info(
33
+ "Query served | policy_id=%s | q='%s'",
34
+ body.policy_id,
35
+ body.question[:50],
36
+ )
37
+
38
+ return QueryResponse(
39
+ answer=result["answer"],
40
+ policy_id=result.get("policy_id", body.policy_id),
41
+ source_count=result["source_count"],
42
+ sources=result["sources"],
43
+ status="success",
44
+ )
api/schemas.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pydantic request / response models for the PolicyDecoder RAG API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ # ------------------------------------------------------------------ #
11
+ # Query
12
+ # ------------------------------------------------------------------ #
13
+ class QueryRequest(BaseModel):
14
+ question: str
15
+ policy_id: str
16
+ k: int = 8
17
+
18
+
19
+ class SourceItem(BaseModel):
20
+ section: str
21
+ clause_type: str
22
+ page_number: Optional[int] = None
23
+ highlight_text: Optional[str] = None
24
+ relevance_score: float
25
+ snippet: str
26
+
27
+
28
+ class QueryResponse(BaseModel):
29
+ answer: str
30
+ policy_id: str
31
+ source_count: int
32
+ sources: list[SourceItem]
33
+ status: str = "success"
34
+
35
+
36
+ # ------------------------------------------------------------------ #
37
+ # Ingest
38
+ # ------------------------------------------------------------------ #
39
+ class IngestRequest(BaseModel):
40
+ policy_id: str
41
+ pdf_url: str | None = None # optional: download from URL
42
+ overwrite: bool = False
43
+
44
+
45
+ class IngestResponse(BaseModel):
46
+ status: str # "success", "skipped", "processing"
47
+ policy_id: str
48
+ chunks: int = 0
49
+ message: str = ""
50
+
51
+
52
+ # ------------------------------------------------------------------ #
53
+ # Health
54
+ # ------------------------------------------------------------------ #
55
+ class HealthResponse(BaseModel):
56
+ status: str
57
+ version: str
58
+ supabase_connected: bool
59
+ model: str
60
+
61
+
62
+ # ------------------------------------------------------------------ #
63
+ # Policy Summary
64
+ # ------------------------------------------------------------------ #
65
+ class PolicySummaryResponse(BaseModel):
66
+ policy_id: str
67
+ summary: dict
backend/.env.example ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ PORT=4000
2
+ SUPABASE_URL=https://your-project.supabase.co
3
+ SUPABASE_SERVICE_KEY=your-service-role-key
4
+ JWT_SECRET=your-super-secret-jwt-key
5
+ PYTHON_API_URL=http://localhost:8000
backend/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ node_modules/
2
+ .env
backend/node_modules/.package-lock.json ADDED
@@ -0,0 +1,1431 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "backend",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "node_modules/@supabase/auth-js": {
8
+ "version": "2.99.1",
9
+ "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.99.1.tgz",
10
+ "integrity": "sha512-x7lKKTvKjABJt/FYcRSPiTT01Xhm2FF8RhfL8+RHMkmlwmRQ88/lREupIHKwFPW0W6pTCJqkZb7Yhpw/EZ+fNw==",
11
+ "license": "MIT",
12
+ "dependencies": {
13
+ "tslib": "2.8.1"
14
+ },
15
+ "engines": {
16
+ "node": ">=20.0.0"
17
+ }
18
+ },
19
+ "node_modules/@supabase/functions-js": {
20
+ "version": "2.99.1",
21
+ "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.99.1.tgz",
22
+ "integrity": "sha512-WQE62W5geYImCO4jzFxCk/avnK7JmOdtqu2eiPz3zOaNiIJajNRSAwMMDgEGd2EMs+sUVYj1LfBjfmW3EzHgIA==",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "tslib": "2.8.1"
26
+ },
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ }
30
+ },
31
+ "node_modules/@supabase/postgrest-js": {
32
+ "version": "2.99.1",
33
+ "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.99.1.tgz",
34
+ "integrity": "sha512-gtw2ibJrADvfqrpUWXGNlrYUvxttF4WVWfPpTFKOb2IRj7B6YRWMDgcrYqIuD4ZEabK4m6YKQCCGy6clgf1lPA==",
35
+ "license": "MIT",
36
+ "dependencies": {
37
+ "tslib": "2.8.1"
38
+ },
39
+ "engines": {
40
+ "node": ">=20.0.0"
41
+ }
42
+ },
43
+ "node_modules/@supabase/realtime-js": {
44
+ "version": "2.99.1",
45
+ "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.99.1.tgz",
46
+ "integrity": "sha512-9EDdy/5wOseGFqxW88ShV9JMRhm7f+9JGY5x+LqT8c7R0X1CTLwg5qie8FiBWcXTZ+68yYxVWunI+7W4FhkWOg==",
47
+ "license": "MIT",
48
+ "dependencies": {
49
+ "@types/phoenix": "^1.6.6",
50
+ "@types/ws": "^8.18.1",
51
+ "tslib": "2.8.1",
52
+ "ws": "^8.18.2"
53
+ },
54
+ "engines": {
55
+ "node": ">=20.0.0"
56
+ }
57
+ },
58
+ "node_modules/@supabase/storage-js": {
59
+ "version": "2.99.1",
60
+ "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.99.1.tgz",
61
+ "integrity": "sha512-mf7zPfqofI62SOoyQJeNUVxe72E4rQsbWim6lTDPeLu3lHija/cP5utlQADGrjeTgOUN6znx/rWn7SjrETP1dw==",
62
+ "license": "MIT",
63
+ "dependencies": {
64
+ "iceberg-js": "^0.8.1",
65
+ "tslib": "2.8.1"
66
+ },
67
+ "engines": {
68
+ "node": ">=20.0.0"
69
+ }
70
+ },
71
+ "node_modules/@supabase/supabase-js": {
72
+ "version": "2.99.1",
73
+ "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.99.1.tgz",
74
+ "integrity": "sha512-5MRoYD9ffXq8F6a036dm65YoSHisC3by/d22mauKE99Vrwf792KxYIIr/iqCX7E4hkuugbPZ5EGYHTB7MKy6Vg==",
75
+ "license": "MIT",
76
+ "dependencies": {
77
+ "@supabase/auth-js": "2.99.1",
78
+ "@supabase/functions-js": "2.99.1",
79
+ "@supabase/postgrest-js": "2.99.1",
80
+ "@supabase/realtime-js": "2.99.1",
81
+ "@supabase/storage-js": "2.99.1"
82
+ },
83
+ "engines": {
84
+ "node": ">=20.0.0"
85
+ }
86
+ },
87
+ "node_modules/@types/node": {
88
+ "version": "25.4.0",
89
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz",
90
+ "integrity": "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==",
91
+ "license": "MIT",
92
+ "dependencies": {
93
+ "undici-types": "~7.18.0"
94
+ }
95
+ },
96
+ "node_modules/@types/phoenix": {
97
+ "version": "1.6.7",
98
+ "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz",
99
+ "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==",
100
+ "license": "MIT"
101
+ },
102
+ "node_modules/@types/ws": {
103
+ "version": "8.18.1",
104
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
105
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
106
+ "license": "MIT",
107
+ "dependencies": {
108
+ "@types/node": "*"
109
+ }
110
+ },
111
+ "node_modules/accepts": {
112
+ "version": "2.0.0",
113
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
114
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
115
+ "license": "MIT",
116
+ "dependencies": {
117
+ "mime-types": "^3.0.0",
118
+ "negotiator": "^1.0.0"
119
+ },
120
+ "engines": {
121
+ "node": ">= 0.6"
122
+ }
123
+ },
124
+ "node_modules/append-field": {
125
+ "version": "1.0.0",
126
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
127
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
128
+ "license": "MIT"
129
+ },
130
+ "node_modules/asynckit": {
131
+ "version": "0.4.0",
132
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
133
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
134
+ "license": "MIT"
135
+ },
136
+ "node_modules/axios": {
137
+ "version": "1.13.6",
138
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
139
+ "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
140
+ "license": "MIT",
141
+ "dependencies": {
142
+ "follow-redirects": "^1.15.11",
143
+ "form-data": "^4.0.5",
144
+ "proxy-from-env": "^1.1.0"
145
+ }
146
+ },
147
+ "node_modules/bcryptjs": {
148
+ "version": "3.0.3",
149
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz",
150
+ "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==",
151
+ "license": "BSD-3-Clause",
152
+ "bin": {
153
+ "bcrypt": "bin/bcrypt"
154
+ }
155
+ },
156
+ "node_modules/body-parser": {
157
+ "version": "2.2.2",
158
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
159
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
160
+ "license": "MIT",
161
+ "dependencies": {
162
+ "bytes": "^3.1.2",
163
+ "content-type": "^1.0.5",
164
+ "debug": "^4.4.3",
165
+ "http-errors": "^2.0.0",
166
+ "iconv-lite": "^0.7.0",
167
+ "on-finished": "^2.4.1",
168
+ "qs": "^6.14.1",
169
+ "raw-body": "^3.0.1",
170
+ "type-is": "^2.0.1"
171
+ },
172
+ "engines": {
173
+ "node": ">=18"
174
+ },
175
+ "funding": {
176
+ "type": "opencollective",
177
+ "url": "https://opencollective.com/express"
178
+ }
179
+ },
180
+ "node_modules/buffer-equal-constant-time": {
181
+ "version": "1.0.1",
182
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
183
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
184
+ "license": "BSD-3-Clause"
185
+ },
186
+ "node_modules/buffer-from": {
187
+ "version": "1.1.2",
188
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
189
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
190
+ "license": "MIT"
191
+ },
192
+ "node_modules/busboy": {
193
+ "version": "1.6.0",
194
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
195
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
196
+ "dependencies": {
197
+ "streamsearch": "^1.1.0"
198
+ },
199
+ "engines": {
200
+ "node": ">=10.16.0"
201
+ }
202
+ },
203
+ "node_modules/bytes": {
204
+ "version": "3.1.2",
205
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
206
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
207
+ "license": "MIT",
208
+ "engines": {
209
+ "node": ">= 0.8"
210
+ }
211
+ },
212
+ "node_modules/call-bind-apply-helpers": {
213
+ "version": "1.0.2",
214
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
215
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
216
+ "license": "MIT",
217
+ "dependencies": {
218
+ "es-errors": "^1.3.0",
219
+ "function-bind": "^1.1.2"
220
+ },
221
+ "engines": {
222
+ "node": ">= 0.4"
223
+ }
224
+ },
225
+ "node_modules/call-bound": {
226
+ "version": "1.0.4",
227
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
228
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
229
+ "license": "MIT",
230
+ "dependencies": {
231
+ "call-bind-apply-helpers": "^1.0.2",
232
+ "get-intrinsic": "^1.3.0"
233
+ },
234
+ "engines": {
235
+ "node": ">= 0.4"
236
+ },
237
+ "funding": {
238
+ "url": "https://github.com/sponsors/ljharb"
239
+ }
240
+ },
241
+ "node_modules/combined-stream": {
242
+ "version": "1.0.8",
243
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
244
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
245
+ "license": "MIT",
246
+ "dependencies": {
247
+ "delayed-stream": "~1.0.0"
248
+ },
249
+ "engines": {
250
+ "node": ">= 0.8"
251
+ }
252
+ },
253
+ "node_modules/concat-stream": {
254
+ "version": "2.0.0",
255
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
256
+ "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
257
+ "engines": [
258
+ "node >= 6.0"
259
+ ],
260
+ "license": "MIT",
261
+ "dependencies": {
262
+ "buffer-from": "^1.0.0",
263
+ "inherits": "^2.0.3",
264
+ "readable-stream": "^3.0.2",
265
+ "typedarray": "^0.0.6"
266
+ }
267
+ },
268
+ "node_modules/content-disposition": {
269
+ "version": "1.0.1",
270
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
271
+ "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
272
+ "license": "MIT",
273
+ "engines": {
274
+ "node": ">=18"
275
+ },
276
+ "funding": {
277
+ "type": "opencollective",
278
+ "url": "https://opencollective.com/express"
279
+ }
280
+ },
281
+ "node_modules/content-type": {
282
+ "version": "1.0.5",
283
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
284
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
285
+ "license": "MIT",
286
+ "engines": {
287
+ "node": ">= 0.6"
288
+ }
289
+ },
290
+ "node_modules/cookie": {
291
+ "version": "0.7.2",
292
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
293
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
294
+ "license": "MIT",
295
+ "engines": {
296
+ "node": ">= 0.6"
297
+ }
298
+ },
299
+ "node_modules/cookie-signature": {
300
+ "version": "1.2.2",
301
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
302
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
303
+ "license": "MIT",
304
+ "engines": {
305
+ "node": ">=6.6.0"
306
+ }
307
+ },
308
+ "node_modules/cors": {
309
+ "version": "2.8.6",
310
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
311
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
312
+ "license": "MIT",
313
+ "dependencies": {
314
+ "object-assign": "^4",
315
+ "vary": "^1"
316
+ },
317
+ "engines": {
318
+ "node": ">= 0.10"
319
+ },
320
+ "funding": {
321
+ "type": "opencollective",
322
+ "url": "https://opencollective.com/express"
323
+ }
324
+ },
325
+ "node_modules/debug": {
326
+ "version": "4.4.3",
327
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
328
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
329
+ "license": "MIT",
330
+ "dependencies": {
331
+ "ms": "^2.1.3"
332
+ },
333
+ "engines": {
334
+ "node": ">=6.0"
335
+ },
336
+ "peerDependenciesMeta": {
337
+ "supports-color": {
338
+ "optional": true
339
+ }
340
+ }
341
+ },
342
+ "node_modules/delayed-stream": {
343
+ "version": "1.0.0",
344
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
345
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
346
+ "license": "MIT",
347
+ "engines": {
348
+ "node": ">=0.4.0"
349
+ }
350
+ },
351
+ "node_modules/depd": {
352
+ "version": "2.0.0",
353
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
354
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
355
+ "license": "MIT",
356
+ "engines": {
357
+ "node": ">= 0.8"
358
+ }
359
+ },
360
+ "node_modules/dotenv": {
361
+ "version": "17.3.1",
362
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
363
+ "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
364
+ "license": "BSD-2-Clause",
365
+ "engines": {
366
+ "node": ">=12"
367
+ },
368
+ "funding": {
369
+ "url": "https://dotenvx.com"
370
+ }
371
+ },
372
+ "node_modules/dunder-proto": {
373
+ "version": "1.0.1",
374
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
375
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
376
+ "license": "MIT",
377
+ "dependencies": {
378
+ "call-bind-apply-helpers": "^1.0.1",
379
+ "es-errors": "^1.3.0",
380
+ "gopd": "^1.2.0"
381
+ },
382
+ "engines": {
383
+ "node": ">= 0.4"
384
+ }
385
+ },
386
+ "node_modules/ecdsa-sig-formatter": {
387
+ "version": "1.0.11",
388
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
389
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
390
+ "license": "Apache-2.0",
391
+ "dependencies": {
392
+ "safe-buffer": "^5.0.1"
393
+ }
394
+ },
395
+ "node_modules/ee-first": {
396
+ "version": "1.1.1",
397
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
398
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
399
+ "license": "MIT"
400
+ },
401
+ "node_modules/encodeurl": {
402
+ "version": "2.0.0",
403
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
404
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
405
+ "license": "MIT",
406
+ "engines": {
407
+ "node": ">= 0.8"
408
+ }
409
+ },
410
+ "node_modules/es-define-property": {
411
+ "version": "1.0.1",
412
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
413
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
414
+ "license": "MIT",
415
+ "engines": {
416
+ "node": ">= 0.4"
417
+ }
418
+ },
419
+ "node_modules/es-errors": {
420
+ "version": "1.3.0",
421
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
422
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
423
+ "license": "MIT",
424
+ "engines": {
425
+ "node": ">= 0.4"
426
+ }
427
+ },
428
+ "node_modules/es-object-atoms": {
429
+ "version": "1.1.1",
430
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
431
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
432
+ "license": "MIT",
433
+ "dependencies": {
434
+ "es-errors": "^1.3.0"
435
+ },
436
+ "engines": {
437
+ "node": ">= 0.4"
438
+ }
439
+ },
440
+ "node_modules/es-set-tostringtag": {
441
+ "version": "2.1.0",
442
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
443
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
444
+ "license": "MIT",
445
+ "dependencies": {
446
+ "es-errors": "^1.3.0",
447
+ "get-intrinsic": "^1.2.6",
448
+ "has-tostringtag": "^1.0.2",
449
+ "hasown": "^2.0.2"
450
+ },
451
+ "engines": {
452
+ "node": ">= 0.4"
453
+ }
454
+ },
455
+ "node_modules/escape-html": {
456
+ "version": "1.0.3",
457
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
458
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
459
+ "license": "MIT"
460
+ },
461
+ "node_modules/etag": {
462
+ "version": "1.8.1",
463
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
464
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
465
+ "license": "MIT",
466
+ "engines": {
467
+ "node": ">= 0.6"
468
+ }
469
+ },
470
+ "node_modules/express": {
471
+ "version": "5.2.1",
472
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
473
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
474
+ "license": "MIT",
475
+ "dependencies": {
476
+ "accepts": "^2.0.0",
477
+ "body-parser": "^2.2.1",
478
+ "content-disposition": "^1.0.0",
479
+ "content-type": "^1.0.5",
480
+ "cookie": "^0.7.1",
481
+ "cookie-signature": "^1.2.1",
482
+ "debug": "^4.4.0",
483
+ "depd": "^2.0.0",
484
+ "encodeurl": "^2.0.0",
485
+ "escape-html": "^1.0.3",
486
+ "etag": "^1.8.1",
487
+ "finalhandler": "^2.1.0",
488
+ "fresh": "^2.0.0",
489
+ "http-errors": "^2.0.0",
490
+ "merge-descriptors": "^2.0.0",
491
+ "mime-types": "^3.0.0",
492
+ "on-finished": "^2.4.1",
493
+ "once": "^1.4.0",
494
+ "parseurl": "^1.3.3",
495
+ "proxy-addr": "^2.0.7",
496
+ "qs": "^6.14.0",
497
+ "range-parser": "^1.2.1",
498
+ "router": "^2.2.0",
499
+ "send": "^1.1.0",
500
+ "serve-static": "^2.2.0",
501
+ "statuses": "^2.0.1",
502
+ "type-is": "^2.0.1",
503
+ "vary": "^1.1.2"
504
+ },
505
+ "engines": {
506
+ "node": ">= 18"
507
+ },
508
+ "funding": {
509
+ "type": "opencollective",
510
+ "url": "https://opencollective.com/express"
511
+ }
512
+ },
513
+ "node_modules/finalhandler": {
514
+ "version": "2.1.1",
515
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
516
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
517
+ "license": "MIT",
518
+ "dependencies": {
519
+ "debug": "^4.4.0",
520
+ "encodeurl": "^2.0.0",
521
+ "escape-html": "^1.0.3",
522
+ "on-finished": "^2.4.1",
523
+ "parseurl": "^1.3.3",
524
+ "statuses": "^2.0.1"
525
+ },
526
+ "engines": {
527
+ "node": ">= 18.0.0"
528
+ },
529
+ "funding": {
530
+ "type": "opencollective",
531
+ "url": "https://opencollective.com/express"
532
+ }
533
+ },
534
+ "node_modules/follow-redirects": {
535
+ "version": "1.15.11",
536
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
537
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
538
+ "funding": [
539
+ {
540
+ "type": "individual",
541
+ "url": "https://github.com/sponsors/RubenVerborgh"
542
+ }
543
+ ],
544
+ "license": "MIT",
545
+ "engines": {
546
+ "node": ">=4.0"
547
+ },
548
+ "peerDependenciesMeta": {
549
+ "debug": {
550
+ "optional": true
551
+ }
552
+ }
553
+ },
554
+ "node_modules/form-data": {
555
+ "version": "4.0.5",
556
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
557
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
558
+ "license": "MIT",
559
+ "dependencies": {
560
+ "asynckit": "^0.4.0",
561
+ "combined-stream": "^1.0.8",
562
+ "es-set-tostringtag": "^2.1.0",
563
+ "hasown": "^2.0.2",
564
+ "mime-types": "^2.1.12"
565
+ },
566
+ "engines": {
567
+ "node": ">= 6"
568
+ }
569
+ },
570
+ "node_modules/form-data/node_modules/mime-db": {
571
+ "version": "1.52.0",
572
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
573
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
574
+ "license": "MIT",
575
+ "engines": {
576
+ "node": ">= 0.6"
577
+ }
578
+ },
579
+ "node_modules/form-data/node_modules/mime-types": {
580
+ "version": "2.1.35",
581
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
582
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
583
+ "license": "MIT",
584
+ "dependencies": {
585
+ "mime-db": "1.52.0"
586
+ },
587
+ "engines": {
588
+ "node": ">= 0.6"
589
+ }
590
+ },
591
+ "node_modules/forwarded": {
592
+ "version": "0.2.0",
593
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
594
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
595
+ "license": "MIT",
596
+ "engines": {
597
+ "node": ">= 0.6"
598
+ }
599
+ },
600
+ "node_modules/fresh": {
601
+ "version": "2.0.0",
602
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
603
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
604
+ "license": "MIT",
605
+ "engines": {
606
+ "node": ">= 0.8"
607
+ }
608
+ },
609
+ "node_modules/function-bind": {
610
+ "version": "1.1.2",
611
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
612
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
613
+ "license": "MIT",
614
+ "funding": {
615
+ "url": "https://github.com/sponsors/ljharb"
616
+ }
617
+ },
618
+ "node_modules/get-intrinsic": {
619
+ "version": "1.3.0",
620
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
621
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
622
+ "license": "MIT",
623
+ "dependencies": {
624
+ "call-bind-apply-helpers": "^1.0.2",
625
+ "es-define-property": "^1.0.1",
626
+ "es-errors": "^1.3.0",
627
+ "es-object-atoms": "^1.1.1",
628
+ "function-bind": "^1.1.2",
629
+ "get-proto": "^1.0.1",
630
+ "gopd": "^1.2.0",
631
+ "has-symbols": "^1.1.0",
632
+ "hasown": "^2.0.2",
633
+ "math-intrinsics": "^1.1.0"
634
+ },
635
+ "engines": {
636
+ "node": ">= 0.4"
637
+ },
638
+ "funding": {
639
+ "url": "https://github.com/sponsors/ljharb"
640
+ }
641
+ },
642
+ "node_modules/get-proto": {
643
+ "version": "1.0.1",
644
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
645
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
646
+ "license": "MIT",
647
+ "dependencies": {
648
+ "dunder-proto": "^1.0.1",
649
+ "es-object-atoms": "^1.0.0"
650
+ },
651
+ "engines": {
652
+ "node": ">= 0.4"
653
+ }
654
+ },
655
+ "node_modules/gopd": {
656
+ "version": "1.2.0",
657
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
658
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
659
+ "license": "MIT",
660
+ "engines": {
661
+ "node": ">= 0.4"
662
+ },
663
+ "funding": {
664
+ "url": "https://github.com/sponsors/ljharb"
665
+ }
666
+ },
667
+ "node_modules/has-symbols": {
668
+ "version": "1.1.0",
669
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
670
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
671
+ "license": "MIT",
672
+ "engines": {
673
+ "node": ">= 0.4"
674
+ },
675
+ "funding": {
676
+ "url": "https://github.com/sponsors/ljharb"
677
+ }
678
+ },
679
+ "node_modules/has-tostringtag": {
680
+ "version": "1.0.2",
681
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
682
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
683
+ "license": "MIT",
684
+ "dependencies": {
685
+ "has-symbols": "^1.0.3"
686
+ },
687
+ "engines": {
688
+ "node": ">= 0.4"
689
+ },
690
+ "funding": {
691
+ "url": "https://github.com/sponsors/ljharb"
692
+ }
693
+ },
694
+ "node_modules/hasown": {
695
+ "version": "2.0.2",
696
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
697
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
698
+ "license": "MIT",
699
+ "dependencies": {
700
+ "function-bind": "^1.1.2"
701
+ },
702
+ "engines": {
703
+ "node": ">= 0.4"
704
+ }
705
+ },
706
+ "node_modules/http-errors": {
707
+ "version": "2.0.1",
708
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
709
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
710
+ "license": "MIT",
711
+ "dependencies": {
712
+ "depd": "~2.0.0",
713
+ "inherits": "~2.0.4",
714
+ "setprototypeof": "~1.2.0",
715
+ "statuses": "~2.0.2",
716
+ "toidentifier": "~1.0.1"
717
+ },
718
+ "engines": {
719
+ "node": ">= 0.8"
720
+ },
721
+ "funding": {
722
+ "type": "opencollective",
723
+ "url": "https://opencollective.com/express"
724
+ }
725
+ },
726
+ "node_modules/iceberg-js": {
727
+ "version": "0.8.1",
728
+ "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz",
729
+ "integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==",
730
+ "license": "MIT",
731
+ "engines": {
732
+ "node": ">=20.0.0"
733
+ }
734
+ },
735
+ "node_modules/iconv-lite": {
736
+ "version": "0.7.2",
737
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
738
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
739
+ "license": "MIT",
740
+ "dependencies": {
741
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
742
+ },
743
+ "engines": {
744
+ "node": ">=0.10.0"
745
+ },
746
+ "funding": {
747
+ "type": "opencollective",
748
+ "url": "https://opencollective.com/express"
749
+ }
750
+ },
751
+ "node_modules/inherits": {
752
+ "version": "2.0.4",
753
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
754
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
755
+ "license": "ISC"
756
+ },
757
+ "node_modules/ipaddr.js": {
758
+ "version": "1.9.1",
759
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
760
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
761
+ "license": "MIT",
762
+ "engines": {
763
+ "node": ">= 0.10"
764
+ }
765
+ },
766
+ "node_modules/is-promise": {
767
+ "version": "4.0.0",
768
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
769
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
770
+ "license": "MIT"
771
+ },
772
+ "node_modules/jsonwebtoken": {
773
+ "version": "9.0.3",
774
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
775
+ "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
776
+ "license": "MIT",
777
+ "dependencies": {
778
+ "jws": "^4.0.1",
779
+ "lodash.includes": "^4.3.0",
780
+ "lodash.isboolean": "^3.0.3",
781
+ "lodash.isinteger": "^4.0.4",
782
+ "lodash.isnumber": "^3.0.3",
783
+ "lodash.isplainobject": "^4.0.6",
784
+ "lodash.isstring": "^4.0.1",
785
+ "lodash.once": "^4.0.0",
786
+ "ms": "^2.1.1",
787
+ "semver": "^7.5.4"
788
+ },
789
+ "engines": {
790
+ "node": ">=12",
791
+ "npm": ">=6"
792
+ }
793
+ },
794
+ "node_modules/jwa": {
795
+ "version": "2.0.1",
796
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
797
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
798
+ "license": "MIT",
799
+ "dependencies": {
800
+ "buffer-equal-constant-time": "^1.0.1",
801
+ "ecdsa-sig-formatter": "1.0.11",
802
+ "safe-buffer": "^5.0.1"
803
+ }
804
+ },
805
+ "node_modules/jws": {
806
+ "version": "4.0.1",
807
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
808
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
809
+ "license": "MIT",
810
+ "dependencies": {
811
+ "jwa": "^2.0.1",
812
+ "safe-buffer": "^5.0.1"
813
+ }
814
+ },
815
+ "node_modules/lodash.includes": {
816
+ "version": "4.3.0",
817
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
818
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
819
+ "license": "MIT"
820
+ },
821
+ "node_modules/lodash.isboolean": {
822
+ "version": "3.0.3",
823
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
824
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
825
+ "license": "MIT"
826
+ },
827
+ "node_modules/lodash.isinteger": {
828
+ "version": "4.0.4",
829
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
830
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
831
+ "license": "MIT"
832
+ },
833
+ "node_modules/lodash.isnumber": {
834
+ "version": "3.0.3",
835
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
836
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
837
+ "license": "MIT"
838
+ },
839
+ "node_modules/lodash.isplainobject": {
840
+ "version": "4.0.6",
841
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
842
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
843
+ "license": "MIT"
844
+ },
845
+ "node_modules/lodash.isstring": {
846
+ "version": "4.0.1",
847
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
848
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
849
+ "license": "MIT"
850
+ },
851
+ "node_modules/lodash.once": {
852
+ "version": "4.1.1",
853
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
854
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
855
+ "license": "MIT"
856
+ },
857
+ "node_modules/math-intrinsics": {
858
+ "version": "1.1.0",
859
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
860
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
861
+ "license": "MIT",
862
+ "engines": {
863
+ "node": ">= 0.4"
864
+ }
865
+ },
866
+ "node_modules/media-typer": {
867
+ "version": "1.1.0",
868
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
869
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
870
+ "license": "MIT",
871
+ "engines": {
872
+ "node": ">= 0.8"
873
+ }
874
+ },
875
+ "node_modules/merge-descriptors": {
876
+ "version": "2.0.0",
877
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
878
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
879
+ "license": "MIT",
880
+ "engines": {
881
+ "node": ">=18"
882
+ },
883
+ "funding": {
884
+ "url": "https://github.com/sponsors/sindresorhus"
885
+ }
886
+ },
887
+ "node_modules/mime-db": {
888
+ "version": "1.54.0",
889
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
890
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
891
+ "license": "MIT",
892
+ "engines": {
893
+ "node": ">= 0.6"
894
+ }
895
+ },
896
+ "node_modules/mime-types": {
897
+ "version": "3.0.2",
898
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
899
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
900
+ "license": "MIT",
901
+ "dependencies": {
902
+ "mime-db": "^1.54.0"
903
+ },
904
+ "engines": {
905
+ "node": ">=18"
906
+ },
907
+ "funding": {
908
+ "type": "opencollective",
909
+ "url": "https://opencollective.com/express"
910
+ }
911
+ },
912
+ "node_modules/ms": {
913
+ "version": "2.1.3",
914
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
915
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
916
+ "license": "MIT"
917
+ },
918
+ "node_modules/multer": {
919
+ "version": "2.1.1",
920
+ "resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz",
921
+ "integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==",
922
+ "license": "MIT",
923
+ "dependencies": {
924
+ "append-field": "^1.0.0",
925
+ "busboy": "^1.6.0",
926
+ "concat-stream": "^2.0.0",
927
+ "type-is": "^1.6.18"
928
+ },
929
+ "engines": {
930
+ "node": ">= 10.16.0"
931
+ },
932
+ "funding": {
933
+ "type": "opencollective",
934
+ "url": "https://opencollective.com/express"
935
+ }
936
+ },
937
+ "node_modules/multer/node_modules/media-typer": {
938
+ "version": "0.3.0",
939
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
940
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
941
+ "license": "MIT",
942
+ "engines": {
943
+ "node": ">= 0.6"
944
+ }
945
+ },
946
+ "node_modules/multer/node_modules/mime-db": {
947
+ "version": "1.52.0",
948
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
949
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
950
+ "license": "MIT",
951
+ "engines": {
952
+ "node": ">= 0.6"
953
+ }
954
+ },
955
+ "node_modules/multer/node_modules/mime-types": {
956
+ "version": "2.1.35",
957
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
958
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
959
+ "license": "MIT",
960
+ "dependencies": {
961
+ "mime-db": "1.52.0"
962
+ },
963
+ "engines": {
964
+ "node": ">= 0.6"
965
+ }
966
+ },
967
+ "node_modules/multer/node_modules/type-is": {
968
+ "version": "1.6.18",
969
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
970
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
971
+ "license": "MIT",
972
+ "dependencies": {
973
+ "media-typer": "0.3.0",
974
+ "mime-types": "~2.1.24"
975
+ },
976
+ "engines": {
977
+ "node": ">= 0.6"
978
+ }
979
+ },
980
+ "node_modules/negotiator": {
981
+ "version": "1.0.0",
982
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
983
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
984
+ "license": "MIT",
985
+ "engines": {
986
+ "node": ">= 0.6"
987
+ }
988
+ },
989
+ "node_modules/object-assign": {
990
+ "version": "4.1.1",
991
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
992
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
993
+ "license": "MIT",
994
+ "engines": {
995
+ "node": ">=0.10.0"
996
+ }
997
+ },
998
+ "node_modules/object-inspect": {
999
+ "version": "1.13.4",
1000
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
1001
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
1002
+ "license": "MIT",
1003
+ "engines": {
1004
+ "node": ">= 0.4"
1005
+ },
1006
+ "funding": {
1007
+ "url": "https://github.com/sponsors/ljharb"
1008
+ }
1009
+ },
1010
+ "node_modules/on-finished": {
1011
+ "version": "2.4.1",
1012
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
1013
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
1014
+ "license": "MIT",
1015
+ "dependencies": {
1016
+ "ee-first": "1.1.1"
1017
+ },
1018
+ "engines": {
1019
+ "node": ">= 0.8"
1020
+ }
1021
+ },
1022
+ "node_modules/once": {
1023
+ "version": "1.4.0",
1024
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1025
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1026
+ "license": "ISC",
1027
+ "dependencies": {
1028
+ "wrappy": "1"
1029
+ }
1030
+ },
1031
+ "node_modules/parseurl": {
1032
+ "version": "1.3.3",
1033
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1034
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
1035
+ "license": "MIT",
1036
+ "engines": {
1037
+ "node": ">= 0.8"
1038
+ }
1039
+ },
1040
+ "node_modules/path-to-regexp": {
1041
+ "version": "8.3.0",
1042
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
1043
+ "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
1044
+ "license": "MIT",
1045
+ "funding": {
1046
+ "type": "opencollective",
1047
+ "url": "https://opencollective.com/express"
1048
+ }
1049
+ },
1050
+ "node_modules/proxy-addr": {
1051
+ "version": "2.0.7",
1052
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
1053
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1054
+ "license": "MIT",
1055
+ "dependencies": {
1056
+ "forwarded": "0.2.0",
1057
+ "ipaddr.js": "1.9.1"
1058
+ },
1059
+ "engines": {
1060
+ "node": ">= 0.10"
1061
+ }
1062
+ },
1063
+ "node_modules/proxy-from-env": {
1064
+ "version": "1.1.0",
1065
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
1066
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
1067
+ "license": "MIT"
1068
+ },
1069
+ "node_modules/qs": {
1070
+ "version": "6.15.0",
1071
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
1072
+ "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
1073
+ "license": "BSD-3-Clause",
1074
+ "dependencies": {
1075
+ "side-channel": "^1.1.0"
1076
+ },
1077
+ "engines": {
1078
+ "node": ">=0.6"
1079
+ },
1080
+ "funding": {
1081
+ "url": "https://github.com/sponsors/ljharb"
1082
+ }
1083
+ },
1084
+ "node_modules/range-parser": {
1085
+ "version": "1.2.1",
1086
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1087
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
1088
+ "license": "MIT",
1089
+ "engines": {
1090
+ "node": ">= 0.6"
1091
+ }
1092
+ },
1093
+ "node_modules/raw-body": {
1094
+ "version": "3.0.2",
1095
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
1096
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
1097
+ "license": "MIT",
1098
+ "dependencies": {
1099
+ "bytes": "~3.1.2",
1100
+ "http-errors": "~2.0.1",
1101
+ "iconv-lite": "~0.7.0",
1102
+ "unpipe": "~1.0.0"
1103
+ },
1104
+ "engines": {
1105
+ "node": ">= 0.10"
1106
+ }
1107
+ },
1108
+ "node_modules/readable-stream": {
1109
+ "version": "3.6.2",
1110
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
1111
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
1112
+ "license": "MIT",
1113
+ "dependencies": {
1114
+ "inherits": "^2.0.3",
1115
+ "string_decoder": "^1.1.1",
1116
+ "util-deprecate": "^1.0.1"
1117
+ },
1118
+ "engines": {
1119
+ "node": ">= 6"
1120
+ }
1121
+ },
1122
+ "node_modules/router": {
1123
+ "version": "2.2.0",
1124
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
1125
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
1126
+ "license": "MIT",
1127
+ "dependencies": {
1128
+ "debug": "^4.4.0",
1129
+ "depd": "^2.0.0",
1130
+ "is-promise": "^4.0.0",
1131
+ "parseurl": "^1.3.3",
1132
+ "path-to-regexp": "^8.0.0"
1133
+ },
1134
+ "engines": {
1135
+ "node": ">= 18"
1136
+ }
1137
+ },
1138
+ "node_modules/safe-buffer": {
1139
+ "version": "5.2.1",
1140
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1141
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1142
+ "funding": [
1143
+ {
1144
+ "type": "github",
1145
+ "url": "https://github.com/sponsors/feross"
1146
+ },
1147
+ {
1148
+ "type": "patreon",
1149
+ "url": "https://www.patreon.com/feross"
1150
+ },
1151
+ {
1152
+ "type": "consulting",
1153
+ "url": "https://feross.org/support"
1154
+ }
1155
+ ],
1156
+ "license": "MIT"
1157
+ },
1158
+ "node_modules/safer-buffer": {
1159
+ "version": "2.1.2",
1160
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1161
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
1162
+ "license": "MIT"
1163
+ },
1164
+ "node_modules/semver": {
1165
+ "version": "7.7.4",
1166
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
1167
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
1168
+ "license": "ISC",
1169
+ "bin": {
1170
+ "semver": "bin/semver.js"
1171
+ },
1172
+ "engines": {
1173
+ "node": ">=10"
1174
+ }
1175
+ },
1176
+ "node_modules/send": {
1177
+ "version": "1.2.1",
1178
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
1179
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
1180
+ "license": "MIT",
1181
+ "dependencies": {
1182
+ "debug": "^4.4.3",
1183
+ "encodeurl": "^2.0.0",
1184
+ "escape-html": "^1.0.3",
1185
+ "etag": "^1.8.1",
1186
+ "fresh": "^2.0.0",
1187
+ "http-errors": "^2.0.1",
1188
+ "mime-types": "^3.0.2",
1189
+ "ms": "^2.1.3",
1190
+ "on-finished": "^2.4.1",
1191
+ "range-parser": "^1.2.1",
1192
+ "statuses": "^2.0.2"
1193
+ },
1194
+ "engines": {
1195
+ "node": ">= 18"
1196
+ },
1197
+ "funding": {
1198
+ "type": "opencollective",
1199
+ "url": "https://opencollective.com/express"
1200
+ }
1201
+ },
1202
+ "node_modules/serve-static": {
1203
+ "version": "2.2.1",
1204
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
1205
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
1206
+ "license": "MIT",
1207
+ "dependencies": {
1208
+ "encodeurl": "^2.0.0",
1209
+ "escape-html": "^1.0.3",
1210
+ "parseurl": "^1.3.3",
1211
+ "send": "^1.2.0"
1212
+ },
1213
+ "engines": {
1214
+ "node": ">= 18"
1215
+ },
1216
+ "funding": {
1217
+ "type": "opencollective",
1218
+ "url": "https://opencollective.com/express"
1219
+ }
1220
+ },
1221
+ "node_modules/setprototypeof": {
1222
+ "version": "1.2.0",
1223
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1224
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
1225
+ "license": "ISC"
1226
+ },
1227
+ "node_modules/side-channel": {
1228
+ "version": "1.1.0",
1229
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
1230
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
1231
+ "license": "MIT",
1232
+ "dependencies": {
1233
+ "es-errors": "^1.3.0",
1234
+ "object-inspect": "^1.13.3",
1235
+ "side-channel-list": "^1.0.0",
1236
+ "side-channel-map": "^1.0.1",
1237
+ "side-channel-weakmap": "^1.0.2"
1238
+ },
1239
+ "engines": {
1240
+ "node": ">= 0.4"
1241
+ },
1242
+ "funding": {
1243
+ "url": "https://github.com/sponsors/ljharb"
1244
+ }
1245
+ },
1246
+ "node_modules/side-channel-list": {
1247
+ "version": "1.0.0",
1248
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
1249
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
1250
+ "license": "MIT",
1251
+ "dependencies": {
1252
+ "es-errors": "^1.3.0",
1253
+ "object-inspect": "^1.13.3"
1254
+ },
1255
+ "engines": {
1256
+ "node": ">= 0.4"
1257
+ },
1258
+ "funding": {
1259
+ "url": "https://github.com/sponsors/ljharb"
1260
+ }
1261
+ },
1262
+ "node_modules/side-channel-map": {
1263
+ "version": "1.0.1",
1264
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
1265
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
1266
+ "license": "MIT",
1267
+ "dependencies": {
1268
+ "call-bound": "^1.0.2",
1269
+ "es-errors": "^1.3.0",
1270
+ "get-intrinsic": "^1.2.5",
1271
+ "object-inspect": "^1.13.3"
1272
+ },
1273
+ "engines": {
1274
+ "node": ">= 0.4"
1275
+ },
1276
+ "funding": {
1277
+ "url": "https://github.com/sponsors/ljharb"
1278
+ }
1279
+ },
1280
+ "node_modules/side-channel-weakmap": {
1281
+ "version": "1.0.2",
1282
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
1283
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
1284
+ "license": "MIT",
1285
+ "dependencies": {
1286
+ "call-bound": "^1.0.2",
1287
+ "es-errors": "^1.3.0",
1288
+ "get-intrinsic": "^1.2.5",
1289
+ "object-inspect": "^1.13.3",
1290
+ "side-channel-map": "^1.0.1"
1291
+ },
1292
+ "engines": {
1293
+ "node": ">= 0.4"
1294
+ },
1295
+ "funding": {
1296
+ "url": "https://github.com/sponsors/ljharb"
1297
+ }
1298
+ },
1299
+ "node_modules/statuses": {
1300
+ "version": "2.0.2",
1301
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
1302
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
1303
+ "license": "MIT",
1304
+ "engines": {
1305
+ "node": ">= 0.8"
1306
+ }
1307
+ },
1308
+ "node_modules/streamsearch": {
1309
+ "version": "1.1.0",
1310
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
1311
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
1312
+ "engines": {
1313
+ "node": ">=10.0.0"
1314
+ }
1315
+ },
1316
+ "node_modules/string_decoder": {
1317
+ "version": "1.3.0",
1318
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
1319
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
1320
+ "license": "MIT",
1321
+ "dependencies": {
1322
+ "safe-buffer": "~5.2.0"
1323
+ }
1324
+ },
1325
+ "node_modules/toidentifier": {
1326
+ "version": "1.0.1",
1327
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1328
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
1329
+ "license": "MIT",
1330
+ "engines": {
1331
+ "node": ">=0.6"
1332
+ }
1333
+ },
1334
+ "node_modules/tslib": {
1335
+ "version": "2.8.1",
1336
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
1337
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
1338
+ "license": "0BSD"
1339
+ },
1340
+ "node_modules/type-is": {
1341
+ "version": "2.0.1",
1342
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
1343
+ "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
1344
+ "license": "MIT",
1345
+ "dependencies": {
1346
+ "content-type": "^1.0.5",
1347
+ "media-typer": "^1.1.0",
1348
+ "mime-types": "^3.0.0"
1349
+ },
1350
+ "engines": {
1351
+ "node": ">= 0.6"
1352
+ }
1353
+ },
1354
+ "node_modules/typedarray": {
1355
+ "version": "0.0.6",
1356
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
1357
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
1358
+ "license": "MIT"
1359
+ },
1360
+ "node_modules/undici-types": {
1361
+ "version": "7.18.2",
1362
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
1363
+ "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
1364
+ "license": "MIT"
1365
+ },
1366
+ "node_modules/unpipe": {
1367
+ "version": "1.0.0",
1368
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1369
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1370
+ "license": "MIT",
1371
+ "engines": {
1372
+ "node": ">= 0.8"
1373
+ }
1374
+ },
1375
+ "node_modules/util-deprecate": {
1376
+ "version": "1.0.2",
1377
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1378
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1379
+ "license": "MIT"
1380
+ },
1381
+ "node_modules/uuid": {
1382
+ "version": "13.0.0",
1383
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
1384
+ "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
1385
+ "funding": [
1386
+ "https://github.com/sponsors/broofa",
1387
+ "https://github.com/sponsors/ctavan"
1388
+ ],
1389
+ "license": "MIT",
1390
+ "bin": {
1391
+ "uuid": "dist-node/bin/uuid"
1392
+ }
1393
+ },
1394
+ "node_modules/vary": {
1395
+ "version": "1.1.2",
1396
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1397
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
1398
+ "license": "MIT",
1399
+ "engines": {
1400
+ "node": ">= 0.8"
1401
+ }
1402
+ },
1403
+ "node_modules/wrappy": {
1404
+ "version": "1.0.2",
1405
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1406
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1407
+ "license": "ISC"
1408
+ },
1409
+ "node_modules/ws": {
1410
+ "version": "8.19.0",
1411
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
1412
+ "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
1413
+ "license": "MIT",
1414
+ "engines": {
1415
+ "node": ">=10.0.0"
1416
+ },
1417
+ "peerDependencies": {
1418
+ "bufferutil": "^4.0.1",
1419
+ "utf-8-validate": ">=5.0.2"
1420
+ },
1421
+ "peerDependenciesMeta": {
1422
+ "bufferutil": {
1423
+ "optional": true
1424
+ },
1425
+ "utf-8-validate": {
1426
+ "optional": true
1427
+ }
1428
+ }
1429
+ }
1430
+ }
1431
+ }
backend/node_modules/asynckit/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Alex Indigo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
backend/node_modules/asynckit/README.md ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # asynckit [![NPM Module](https://img.shields.io/npm/v/asynckit.svg?style=flat)](https://www.npmjs.com/package/asynckit)
2
+
3
+ Minimal async jobs utility library, with streams support.
4
+
5
+ [![PhantomJS Build](https://img.shields.io/travis/alexindigo/asynckit/v0.4.0.svg?label=browser&style=flat)](https://travis-ci.org/alexindigo/asynckit)
6
+ [![Linux Build](https://img.shields.io/travis/alexindigo/asynckit/v0.4.0.svg?label=linux:0.12-6.x&style=flat)](https://travis-ci.org/alexindigo/asynckit)
7
+ [![Windows Build](https://img.shields.io/appveyor/ci/alexindigo/asynckit/v0.4.0.svg?label=windows:0.12-6.x&style=flat)](https://ci.appveyor.com/project/alexindigo/asynckit)
8
+
9
+ [![Coverage Status](https://img.shields.io/coveralls/alexindigo/asynckit/v0.4.0.svg?label=code+coverage&style=flat)](https://coveralls.io/github/alexindigo/asynckit?branch=master)
10
+ [![Dependency Status](https://img.shields.io/david/alexindigo/asynckit/v0.4.0.svg?style=flat)](https://david-dm.org/alexindigo/asynckit)
11
+ [![bitHound Overall Score](https://www.bithound.io/github/alexindigo/asynckit/badges/score.svg)](https://www.bithound.io/github/alexindigo/asynckit)
12
+
13
+ <!-- [![Readme](https://img.shields.io/badge/readme-tested-brightgreen.svg?style=flat)](https://www.npmjs.com/package/reamde) -->
14
+
15
+ AsyncKit provides harness for `parallel` and `serial` iterators over list of items represented by arrays or objects.
16
+ Optionally it accepts abort function (should be synchronously return by iterator for each item), and terminates left over jobs upon an error event. For specific iteration order built-in (`ascending` and `descending`) and custom sort helpers also supported, via `asynckit.serialOrdered` method.
17
+
18
+ It ensures async operations to keep behavior more stable and prevent `Maximum call stack size exceeded` errors, from sync iterators.
19
+
20
+ | compression | size |
21
+ | :----------------- | -------: |
22
+ | asynckit.js | 12.34 kB |
23
+ | asynckit.min.js | 4.11 kB |
24
+ | asynckit.min.js.gz | 1.47 kB |
25
+
26
+
27
+ ## Install
28
+
29
+ ```sh
30
+ $ npm install --save asynckit
31
+ ```
32
+
33
+ ## Examples
34
+
35
+ ### Parallel Jobs
36
+
37
+ Runs iterator over provided array in parallel. Stores output in the `result` array,
38
+ on the matching positions. In unlikely event of an error from one of the jobs,
39
+ will terminate rest of the active jobs (if abort function is provided)
40
+ and return error along with salvaged data to the main callback function.
41
+
42
+ #### Input Array
43
+
44
+ ```javascript
45
+ var parallel = require('asynckit').parallel
46
+ , assert = require('assert')
47
+ ;
48
+
49
+ var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
50
+ , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
51
+ , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ]
52
+ , target = []
53
+ ;
54
+
55
+ parallel(source, asyncJob, function(err, result)
56
+ {
57
+ assert.deepEqual(result, expectedResult);
58
+ assert.deepEqual(target, expectedTarget);
59
+ });
60
+
61
+ // async job accepts one element from the array
62
+ // and a callback function
63
+ function asyncJob(item, cb)
64
+ {
65
+ // different delays (in ms) per item
66
+ var delay = item * 25;
67
+
68
+ // pretend different jobs take different time to finish
69
+ // and not in consequential order
70
+ var timeoutId = setTimeout(function() {
71
+ target.push(item);
72
+ cb(null, item * 2);
73
+ }, delay);
74
+
75
+ // allow to cancel "leftover" jobs upon error
76
+ // return function, invoking of which will abort this job
77
+ return clearTimeout.bind(null, timeoutId);
78
+ }
79
+ ```
80
+
81
+ More examples could be found in [test/test-parallel-array.js](test/test-parallel-array.js).
82
+
83
+ #### Input Object
84
+
85
+ Also it supports named jobs, listed via object.
86
+
87
+ ```javascript
88
+ var parallel = require('asynckit/parallel')
89
+ , assert = require('assert')
90
+ ;
91
+
92
+ var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 }
93
+ , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 }
94
+ , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ]
95
+ , expectedKeys = [ 'first', 'one', 'two', 'four', 'eight', 'sixteen', 'thirtyTwo', 'sixtyFour' ]
96
+ , target = []
97
+ , keys = []
98
+ ;
99
+
100
+ parallel(source, asyncJob, function(err, result)
101
+ {
102
+ assert.deepEqual(result, expectedResult);
103
+ assert.deepEqual(target, expectedTarget);
104
+ assert.deepEqual(keys, expectedKeys);
105
+ });
106
+
107
+ // supports full value, key, callback (shortcut) interface
108
+ function asyncJob(item, key, cb)
109
+ {
110
+ // different delays (in ms) per item
111
+ var delay = item * 25;
112
+
113
+ // pretend different jobs take different time to finish
114
+ // and not in consequential order
115
+ var timeoutId = setTimeout(function() {
116
+ keys.push(key);
117
+ target.push(item);
118
+ cb(null, item * 2);
119
+ }, delay);
120
+
121
+ // allow to cancel "leftover" jobs upon error
122
+ // return function, invoking of which will abort this job
123
+ return clearTimeout.bind(null, timeoutId);
124
+ }
125
+ ```
126
+
127
+ More examples could be found in [test/test-parallel-object.js](test/test-parallel-object.js).
128
+
129
+ ### Serial Jobs
130
+
131
+ Runs iterator over provided array sequentially. Stores output in the `result` array,
132
+ on the matching positions. In unlikely event of an error from one of the jobs,
133
+ will not proceed to the rest of the items in the list
134
+ and return error along with salvaged data to the main callback function.
135
+
136
+ #### Input Array
137
+
138
+ ```javascript
139
+ var serial = require('asynckit/serial')
140
+ , assert = require('assert')
141
+ ;
142
+
143
+ var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
144
+ , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
145
+ , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
146
+ , target = []
147
+ ;
148
+
149
+ serial(source, asyncJob, function(err, result)
150
+ {
151
+ assert.deepEqual(result, expectedResult);
152
+ assert.deepEqual(target, expectedTarget);
153
+ });
154
+
155
+ // extended interface (item, key, callback)
156
+ // also supported for arrays
157
+ function asyncJob(item, key, cb)
158
+ {
159
+ target.push(key);
160
+
161
+ // it will be automatically made async
162
+ // even it iterator "returns" in the same event loop
163
+ cb(null, item * 2);
164
+ }
165
+ ```
166
+
167
+ More examples could be found in [test/test-serial-array.js](test/test-serial-array.js).
168
+
169
+ #### Input Object
170
+
171
+ Also it supports named jobs, listed via object.
172
+
173
+ ```javascript
174
+ var serial = require('asynckit').serial
175
+ , assert = require('assert')
176
+ ;
177
+
178
+ var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
179
+ , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
180
+ , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
181
+ , target = []
182
+ ;
183
+
184
+ var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 }
185
+ , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 }
186
+ , expectedTarget = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
187
+ , target = []
188
+ ;
189
+
190
+
191
+ serial(source, asyncJob, function(err, result)
192
+ {
193
+ assert.deepEqual(result, expectedResult);
194
+ assert.deepEqual(target, expectedTarget);
195
+ });
196
+
197
+ // shortcut interface (item, callback)
198
+ // works for object as well as for the arrays
199
+ function asyncJob(item, cb)
200
+ {
201
+ target.push(item);
202
+
203
+ // it will be automatically made async
204
+ // even it iterator "returns" in the same event loop
205
+ cb(null, item * 2);
206
+ }
207
+ ```
208
+
209
+ More examples could be found in [test/test-serial-object.js](test/test-serial-object.js).
210
+
211
+ _Note: Since _object_ is an _unordered_ collection of properties,
212
+ it may produce unexpected results with sequential iterations.
213
+ Whenever order of the jobs' execution is important please use `serialOrdered` method._
214
+
215
+ ### Ordered Serial Iterations
216
+
217
+ TBD
218
+
219
+ For example [compare-property](compare-property) package.
220
+
221
+ ### Streaming interface
222
+
223
+ TBD
224
+
225
+ ## Want to Know More?
226
+
227
+ More examples can be found in [test folder](test/).
228
+
229
+ Or open an [issue](https://github.com/alexindigo/asynckit/issues) with questions and/or suggestions.
230
+
231
+ ## License
232
+
233
+ AsyncKit is licensed under the MIT license.
backend/node_modules/asynckit/bench.js ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* eslint no-console: "off" */
2
+
3
+ var asynckit = require('./')
4
+ , async = require('async')
5
+ , assert = require('assert')
6
+ , expected = 0
7
+ ;
8
+
9
+ var Benchmark = require('benchmark');
10
+ var suite = new Benchmark.Suite;
11
+
12
+ var source = [];
13
+ for (var z = 1; z < 100; z++)
14
+ {
15
+ source.push(z);
16
+ expected += z;
17
+ }
18
+
19
+ suite
20
+ // add tests
21
+
22
+ .add('async.map', function(deferred)
23
+ {
24
+ var total = 0;
25
+
26
+ async.map(source,
27
+ function(i, cb)
28
+ {
29
+ setImmediate(function()
30
+ {
31
+ total += i;
32
+ cb(null, total);
33
+ });
34
+ },
35
+ function(err, result)
36
+ {
37
+ assert.ifError(err);
38
+ assert.equal(result[result.length - 1], expected);
39
+ deferred.resolve();
40
+ });
41
+ }, {'defer': true})
42
+
43
+
44
+ .add('asynckit.parallel', function(deferred)
45
+ {
46
+ var total = 0;
47
+
48
+ asynckit.parallel(source,
49
+ function(i, cb)
50
+ {
51
+ setImmediate(function()
52
+ {
53
+ total += i;
54
+ cb(null, total);
55
+ });
56
+ },
57
+ function(err, result)
58
+ {
59
+ assert.ifError(err);
60
+ assert.equal(result[result.length - 1], expected);
61
+ deferred.resolve();
62
+ });
63
+ }, {'defer': true})
64
+
65
+
66
+ // add listeners
67
+ .on('cycle', function(ev)
68
+ {
69
+ console.log(String(ev.target));
70
+ })
71
+ .on('complete', function()
72
+ {
73
+ console.log('Fastest is ' + this.filter('fastest').map('name'));
74
+ })
75
+ // run async
76
+ .run({ 'async': true });
backend/node_modules/asynckit/index.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ module.exports =
2
+ {
3
+ parallel : require('./parallel.js'),
4
+ serial : require('./serial.js'),
5
+ serialOrdered : require('./serialOrdered.js')
6
+ };
backend/node_modules/asynckit/lib/abort.js ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // API
2
+ module.exports = abort;
3
+
4
+ /**
5
+ * Aborts leftover active jobs
6
+ *
7
+ * @param {object} state - current state object
8
+ */
9
+ function abort(state)
10
+ {
11
+ Object.keys(state.jobs).forEach(clean.bind(state));
12
+
13
+ // reset leftover jobs
14
+ state.jobs = {};
15
+ }
16
+
17
+ /**
18
+ * Cleans up leftover job by invoking abort function for the provided job id
19
+ *
20
+ * @this state
21
+ * @param {string|number} key - job id to abort
22
+ */
23
+ function clean(key)
24
+ {
25
+ if (typeof this.jobs[key] == 'function')
26
+ {
27
+ this.jobs[key]();
28
+ }
29
+ }
backend/node_modules/asynckit/lib/async.js ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var defer = require('./defer.js');
2
+
3
+ // API
4
+ module.exports = async;
5
+
6
+ /**
7
+ * Runs provided callback asynchronously
8
+ * even if callback itself is not
9
+ *
10
+ * @param {function} callback - callback to invoke
11
+ * @returns {function} - augmented callback
12
+ */
13
+ function async(callback)
14
+ {
15
+ var isAsync = false;
16
+
17
+ // check if async happened
18
+ defer(function() { isAsync = true; });
19
+
20
+ return function async_callback(err, result)
21
+ {
22
+ if (isAsync)
23
+ {
24
+ callback(err, result);
25
+ }
26
+ else
27
+ {
28
+ defer(function nextTick_callback()
29
+ {
30
+ callback(err, result);
31
+ });
32
+ }
33
+ };
34
+ }
backend/node_modules/asynckit/lib/defer.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = defer;
2
+
3
+ /**
4
+ * Runs provided function on next iteration of the event loop
5
+ *
6
+ * @param {function} fn - function to run
7
+ */
8
+ function defer(fn)
9
+ {
10
+ var nextTick = typeof setImmediate == 'function'
11
+ ? setImmediate
12
+ : (
13
+ typeof process == 'object' && typeof process.nextTick == 'function'
14
+ ? process.nextTick
15
+ : null
16
+ );
17
+
18
+ if (nextTick)
19
+ {
20
+ nextTick(fn);
21
+ }
22
+ else
23
+ {
24
+ setTimeout(fn, 0);
25
+ }
26
+ }
backend/node_modules/asynckit/lib/iterate.js ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var async = require('./async.js')
2
+ , abort = require('./abort.js')
3
+ ;
4
+
5
+ // API
6
+ module.exports = iterate;
7
+
8
+ /**
9
+ * Iterates over each job object
10
+ *
11
+ * @param {array|object} list - array or object (named list) to iterate over
12
+ * @param {function} iterator - iterator to run
13
+ * @param {object} state - current job status
14
+ * @param {function} callback - invoked when all elements processed
15
+ */
16
+ function iterate(list, iterator, state, callback)
17
+ {
18
+ // store current index
19
+ var key = state['keyedList'] ? state['keyedList'][state.index] : state.index;
20
+
21
+ state.jobs[key] = runJob(iterator, key, list[key], function(error, output)
22
+ {
23
+ // don't repeat yourself
24
+ // skip secondary callbacks
25
+ if (!(key in state.jobs))
26
+ {
27
+ return;
28
+ }
29
+
30
+ // clean up jobs
31
+ delete state.jobs[key];
32
+
33
+ if (error)
34
+ {
35
+ // don't process rest of the results
36
+ // stop still active jobs
37
+ // and reset the list
38
+ abort(state);
39
+ }
40
+ else
41
+ {
42
+ state.results[key] = output;
43
+ }
44
+
45
+ // return salvaged results
46
+ callback(error, state.results);
47
+ });
48
+ }
49
+
50
+ /**
51
+ * Runs iterator over provided job element
52
+ *
53
+ * @param {function} iterator - iterator to invoke
54
+ * @param {string|number} key - key/index of the element in the list of jobs
55
+ * @param {mixed} item - job description
56
+ * @param {function} callback - invoked after iterator is done with the job
57
+ * @returns {function|mixed} - job abort function or something else
58
+ */
59
+ function runJob(iterator, key, item, callback)
60
+ {
61
+ var aborter;
62
+
63
+ // allow shortcut if iterator expects only two arguments
64
+ if (iterator.length == 2)
65
+ {
66
+ aborter = iterator(item, async(callback));
67
+ }
68
+ // otherwise go with full three arguments
69
+ else
70
+ {
71
+ aborter = iterator(item, key, async(callback));
72
+ }
73
+
74
+ return aborter;
75
+ }
backend/node_modules/asynckit/lib/readable_asynckit.js ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var streamify = require('./streamify.js')
2
+ , defer = require('./defer.js')
3
+ ;
4
+
5
+ // API
6
+ module.exports = ReadableAsyncKit;
7
+
8
+ /**
9
+ * Base constructor for all streams
10
+ * used to hold properties/methods
11
+ */
12
+ function ReadableAsyncKit()
13
+ {
14
+ ReadableAsyncKit.super_.apply(this, arguments);
15
+
16
+ // list of active jobs
17
+ this.jobs = {};
18
+
19
+ // add stream methods
20
+ this.destroy = destroy;
21
+ this._start = _start;
22
+ this._read = _read;
23
+ }
24
+
25
+ /**
26
+ * Destroys readable stream,
27
+ * by aborting outstanding jobs
28
+ *
29
+ * @returns {void}
30
+ */
31
+ function destroy()
32
+ {
33
+ if (this.destroyed)
34
+ {
35
+ return;
36
+ }
37
+
38
+ this.destroyed = true;
39
+
40
+ if (typeof this.terminator == 'function')
41
+ {
42
+ this.terminator();
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Starts provided jobs in async manner
48
+ *
49
+ * @private
50
+ */
51
+ function _start()
52
+ {
53
+ // first argument – runner function
54
+ var runner = arguments[0]
55
+ // take away first argument
56
+ , args = Array.prototype.slice.call(arguments, 1)
57
+ // second argument - input data
58
+ , input = args[0]
59
+ // last argument - result callback
60
+ , endCb = streamify.callback.call(this, args[args.length - 1])
61
+ ;
62
+
63
+ args[args.length - 1] = endCb;
64
+ // third argument - iterator
65
+ args[1] = streamify.iterator.call(this, args[1]);
66
+
67
+ // allow time for proper setup
68
+ defer(function()
69
+ {
70
+ if (!this.destroyed)
71
+ {
72
+ this.terminator = runner.apply(null, args);
73
+ }
74
+ else
75
+ {
76
+ endCb(null, Array.isArray(input) ? [] : {});
77
+ }
78
+ }.bind(this));
79
+ }
80
+
81
+
82
+ /**
83
+ * Implement _read to comply with Readable streams
84
+ * Doesn't really make sense for flowing object mode
85
+ *
86
+ * @private
87
+ */
88
+ function _read()
89
+ {
90
+
91
+ }
backend/node_modules/asynckit/lib/readable_parallel.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var parallel = require('../parallel.js');
2
+
3
+ // API
4
+ module.exports = ReadableParallel;
5
+
6
+ /**
7
+ * Streaming wrapper to `asynckit.parallel`
8
+ *
9
+ * @param {array|object} list - array or object (named list) to iterate over
10
+ * @param {function} iterator - iterator to run
11
+ * @param {function} callback - invoked when all elements processed
12
+ * @returns {stream.Readable#}
13
+ */
14
+ function ReadableParallel(list, iterator, callback)
15
+ {
16
+ if (!(this instanceof ReadableParallel))
17
+ {
18
+ return new ReadableParallel(list, iterator, callback);
19
+ }
20
+
21
+ // turn on object mode
22
+ ReadableParallel.super_.call(this, {objectMode: true});
23
+
24
+ this._start(parallel, list, iterator, callback);
25
+ }
backend/node_modules/asynckit/lib/readable_serial.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var serial = require('../serial.js');
2
+
3
+ // API
4
+ module.exports = ReadableSerial;
5
+
6
+ /**
7
+ * Streaming wrapper to `asynckit.serial`
8
+ *
9
+ * @param {array|object} list - array or object (named list) to iterate over
10
+ * @param {function} iterator - iterator to run
11
+ * @param {function} callback - invoked when all elements processed
12
+ * @returns {stream.Readable#}
13
+ */
14
+ function ReadableSerial(list, iterator, callback)
15
+ {
16
+ if (!(this instanceof ReadableSerial))
17
+ {
18
+ return new ReadableSerial(list, iterator, callback);
19
+ }
20
+
21
+ // turn on object mode
22
+ ReadableSerial.super_.call(this, {objectMode: true});
23
+
24
+ this._start(serial, list, iterator, callback);
25
+ }
backend/node_modules/asynckit/lib/readable_serial_ordered.js ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var serialOrdered = require('../serialOrdered.js');
2
+
3
+ // API
4
+ module.exports = ReadableSerialOrdered;
5
+ // expose sort helpers
6
+ module.exports.ascending = serialOrdered.ascending;
7
+ module.exports.descending = serialOrdered.descending;
8
+
9
+ /**
10
+ * Streaming wrapper to `asynckit.serialOrdered`
11
+ *
12
+ * @param {array|object} list - array or object (named list) to iterate over
13
+ * @param {function} iterator - iterator to run
14
+ * @param {function} sortMethod - custom sort function
15
+ * @param {function} callback - invoked when all elements processed
16
+ * @returns {stream.Readable#}
17
+ */
18
+ function ReadableSerialOrdered(list, iterator, sortMethod, callback)
19
+ {
20
+ if (!(this instanceof ReadableSerialOrdered))
21
+ {
22
+ return new ReadableSerialOrdered(list, iterator, sortMethod, callback);
23
+ }
24
+
25
+ // turn on object mode
26
+ ReadableSerialOrdered.super_.call(this, {objectMode: true});
27
+
28
+ this._start(serialOrdered, list, iterator, sortMethod, callback);
29
+ }
backend/node_modules/asynckit/lib/state.js ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // API
2
+ module.exports = state;
3
+
4
+ /**
5
+ * Creates initial state object
6
+ * for iteration over list
7
+ *
8
+ * @param {array|object} list - list to iterate over
9
+ * @param {function|null} sortMethod - function to use for keys sort,
10
+ * or `null` to keep them as is
11
+ * @returns {object} - initial state object
12
+ */
13
+ function state(list, sortMethod)
14
+ {
15
+ var isNamedList = !Array.isArray(list)
16
+ , initState =
17
+ {
18
+ index : 0,
19
+ keyedList: isNamedList || sortMethod ? Object.keys(list) : null,
20
+ jobs : {},
21
+ results : isNamedList ? {} : [],
22
+ size : isNamedList ? Object.keys(list).length : list.length
23
+ }
24
+ ;
25
+
26
+ if (sortMethod)
27
+ {
28
+ // sort array keys based on it's values
29
+ // sort object's keys just on own merit
30
+ initState.keyedList.sort(isNamedList ? sortMethod : function(a, b)
31
+ {
32
+ return sortMethod(list[a], list[b]);
33
+ });
34
+ }
35
+
36
+ return initState;
37
+ }
backend/node_modules/asynckit/lib/streamify.js ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var async = require('./async.js');
2
+
3
+ // API
4
+ module.exports = {
5
+ iterator: wrapIterator,
6
+ callback: wrapCallback
7
+ };
8
+
9
+ /**
10
+ * Wraps iterators with long signature
11
+ *
12
+ * @this ReadableAsyncKit#
13
+ * @param {function} iterator - function to wrap
14
+ * @returns {function} - wrapped function
15
+ */
16
+ function wrapIterator(iterator)
17
+ {
18
+ var stream = this;
19
+
20
+ return function(item, key, cb)
21
+ {
22
+ var aborter
23
+ , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key))
24
+ ;
25
+
26
+ stream.jobs[key] = wrappedCb;
27
+
28
+ // it's either shortcut (item, cb)
29
+ if (iterator.length == 2)
30
+ {
31
+ aborter = iterator(item, wrappedCb);
32
+ }
33
+ // or long format (item, key, cb)
34
+ else
35
+ {
36
+ aborter = iterator(item, key, wrappedCb);
37
+ }
38
+
39
+ return aborter;
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Wraps provided callback function
45
+ * allowing to execute snitch function before
46
+ * real callback
47
+ *
48
+ * @this ReadableAsyncKit#
49
+ * @param {function} callback - function to wrap
50
+ * @returns {function} - wrapped function
51
+ */
52
+ function wrapCallback(callback)
53
+ {
54
+ var stream = this;
55
+
56
+ var wrapped = function(error, result)
57
+ {
58
+ return finisher.call(stream, error, result, callback);
59
+ };
60
+
61
+ return wrapped;
62
+ }
63
+
64
+ /**
65
+ * Wraps provided iterator callback function
66
+ * makes sure snitch only called once,
67
+ * but passes secondary calls to the original callback
68
+ *
69
+ * @this ReadableAsyncKit#
70
+ * @param {function} callback - callback to wrap
71
+ * @param {number|string} key - iteration key
72
+ * @returns {function} wrapped callback
73
+ */
74
+ function wrapIteratorCallback(callback, key)
75
+ {
76
+ var stream = this;
77
+
78
+ return function(error, output)
79
+ {
80
+ // don't repeat yourself
81
+ if (!(key in stream.jobs))
82
+ {
83
+ callback(error, output);
84
+ return;
85
+ }
86
+
87
+ // clean up jobs
88
+ delete stream.jobs[key];
89
+
90
+ return streamer.call(stream, error, {key: key, value: output}, callback);
91
+ };
92
+ }
93
+
94
+ /**
95
+ * Stream wrapper for iterator callback
96
+ *
97
+ * @this ReadableAsyncKit#
98
+ * @param {mixed} error - error response
99
+ * @param {mixed} output - iterator output
100
+ * @param {function} callback - callback that expects iterator results
101
+ */
102
+ function streamer(error, output, callback)
103
+ {
104
+ if (error && !this.error)
105
+ {
106
+ this.error = error;
107
+ this.pause();
108
+ this.emit('error', error);
109
+ // send back value only, as expected
110
+ callback(error, output && output.value);
111
+ return;
112
+ }
113
+
114
+ // stream stuff
115
+ this.push(output);
116
+
117
+ // back to original track
118
+ // send back value only, as expected
119
+ callback(error, output && output.value);
120
+ }
121
+
122
+ /**
123
+ * Stream wrapper for finishing callback
124
+ *
125
+ * @this ReadableAsyncKit#
126
+ * @param {mixed} error - error response
127
+ * @param {mixed} output - iterator output
128
+ * @param {function} callback - callback that expects final results
129
+ */
130
+ function finisher(error, output, callback)
131
+ {
132
+ // signal end of the stream
133
+ // only for successfully finished streams
134
+ if (!error)
135
+ {
136
+ this.push(null);
137
+ }
138
+
139
+ // back to original track
140
+ callback(error, output);
141
+ }
backend/node_modules/asynckit/lib/terminator.js ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var abort = require('./abort.js')
2
+ , async = require('./async.js')
3
+ ;
4
+
5
+ // API
6
+ module.exports = terminator;
7
+
8
+ /**
9
+ * Terminates jobs in the attached state context
10
+ *
11
+ * @this AsyncKitState#
12
+ * @param {function} callback - final callback to invoke after termination
13
+ */
14
+ function terminator(callback)
15
+ {
16
+ if (!Object.keys(this.jobs).length)
17
+ {
18
+ return;
19
+ }
20
+
21
+ // fast forward iteration index
22
+ this.index = this.size;
23
+
24
+ // abort jobs
25
+ abort(this);
26
+
27
+ // send back results we have so far
28
+ async(callback)(null, this.results);
29
+ }
backend/node_modules/asynckit/package.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "asynckit",
3
+ "version": "0.4.0",
4
+ "description": "Minimal async jobs utility library, with streams support",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "clean": "rimraf coverage",
8
+ "lint": "eslint *.js lib/*.js test/*.js",
9
+ "test": "istanbul cover --reporter=json tape -- 'test/test-*.js' | tap-spec",
10
+ "win-test": "tape test/test-*.js",
11
+ "browser": "browserify -t browserify-istanbul test/lib/browserify_adjustment.js test/test-*.js | obake --coverage | tap-spec",
12
+ "report": "istanbul report",
13
+ "size": "browserify index.js | size-table asynckit",
14
+ "debug": "tape test/test-*.js"
15
+ },
16
+ "pre-commit": [
17
+ "clean",
18
+ "lint",
19
+ "test",
20
+ "browser",
21
+ "report",
22
+ "size"
23
+ ],
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/alexindigo/asynckit.git"
27
+ },
28
+ "keywords": [
29
+ "async",
30
+ "jobs",
31
+ "parallel",
32
+ "serial",
33
+ "iterator",
34
+ "array",
35
+ "object",
36
+ "stream",
37
+ "destroy",
38
+ "terminate",
39
+ "abort"
40
+ ],
41
+ "author": "Alex Indigo <iam@alexindigo.com>",
42
+ "license": "MIT",
43
+ "bugs": {
44
+ "url": "https://github.com/alexindigo/asynckit/issues"
45
+ },
46
+ "homepage": "https://github.com/alexindigo/asynckit#readme",
47
+ "devDependencies": {
48
+ "browserify": "^13.0.0",
49
+ "browserify-istanbul": "^2.0.0",
50
+ "coveralls": "^2.11.9",
51
+ "eslint": "^2.9.0",
52
+ "istanbul": "^0.4.3",
53
+ "obake": "^0.1.2",
54
+ "phantomjs-prebuilt": "^2.1.7",
55
+ "pre-commit": "^1.1.3",
56
+ "reamde": "^1.1.0",
57
+ "rimraf": "^2.5.2",
58
+ "size-table": "^0.2.0",
59
+ "tap-spec": "^4.1.1",
60
+ "tape": "^4.5.1"
61
+ },
62
+ "dependencies": {}
63
+ }
backend/node_modules/asynckit/parallel.js ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var iterate = require('./lib/iterate.js')
2
+ , initState = require('./lib/state.js')
3
+ , terminator = require('./lib/terminator.js')
4
+ ;
5
+
6
+ // Public API
7
+ module.exports = parallel;
8
+
9
+ /**
10
+ * Runs iterator over provided array elements in parallel
11
+ *
12
+ * @param {array|object} list - array or object (named list) to iterate over
13
+ * @param {function} iterator - iterator to run
14
+ * @param {function} callback - invoked when all elements processed
15
+ * @returns {function} - jobs terminator
16
+ */
17
+ function parallel(list, iterator, callback)
18
+ {
19
+ var state = initState(list);
20
+
21
+ while (state.index < (state['keyedList'] || list).length)
22
+ {
23
+ iterate(list, iterator, state, function(error, result)
24
+ {
25
+ if (error)
26
+ {
27
+ callback(error, result);
28
+ return;
29
+ }
30
+
31
+ // looks like it's the last one
32
+ if (Object.keys(state.jobs).length === 0)
33
+ {
34
+ callback(null, state.results);
35
+ return;
36
+ }
37
+ });
38
+
39
+ state.index++;
40
+ }
41
+
42
+ return terminator.bind(state, callback);
43
+ }
backend/node_modules/asynckit/serial.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var serialOrdered = require('./serialOrdered.js');
2
+
3
+ // Public API
4
+ module.exports = serial;
5
+
6
+ /**
7
+ * Runs iterator over provided array elements in series
8
+ *
9
+ * @param {array|object} list - array or object (named list) to iterate over
10
+ * @param {function} iterator - iterator to run
11
+ * @param {function} callback - invoked when all elements processed
12
+ * @returns {function} - jobs terminator
13
+ */
14
+ function serial(list, iterator, callback)
15
+ {
16
+ return serialOrdered(list, iterator, null, callback);
17
+ }
backend/node_modules/asynckit/serialOrdered.js ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var iterate = require('./lib/iterate.js')
2
+ , initState = require('./lib/state.js')
3
+ , terminator = require('./lib/terminator.js')
4
+ ;
5
+
6
+ // Public API
7
+ module.exports = serialOrdered;
8
+ // sorting helpers
9
+ module.exports.ascending = ascending;
10
+ module.exports.descending = descending;
11
+
12
+ /**
13
+ * Runs iterator over provided sorted array elements in series
14
+ *
15
+ * @param {array|object} list - array or object (named list) to iterate over
16
+ * @param {function} iterator - iterator to run
17
+ * @param {function} sortMethod - custom sort function
18
+ * @param {function} callback - invoked when all elements processed
19
+ * @returns {function} - jobs terminator
20
+ */
21
+ function serialOrdered(list, iterator, sortMethod, callback)
22
+ {
23
+ var state = initState(list, sortMethod);
24
+
25
+ iterate(list, iterator, state, function iteratorHandler(error, result)
26
+ {
27
+ if (error)
28
+ {
29
+ callback(error, result);
30
+ return;
31
+ }
32
+
33
+ state.index++;
34
+
35
+ // are we there yet?
36
+ if (state.index < (state['keyedList'] || list).length)
37
+ {
38
+ iterate(list, iterator, state, iteratorHandler);
39
+ return;
40
+ }
41
+
42
+ // done here
43
+ callback(null, state.results);
44
+ });
45
+
46
+ return terminator.bind(state, callback);
47
+ }
48
+
49
+ /*
50
+ * -- Sort methods
51
+ */
52
+
53
+ /**
54
+ * sort helper to sort array elements in ascending order
55
+ *
56
+ * @param {mixed} a - an item to compare
57
+ * @param {mixed} b - an item to compare
58
+ * @returns {number} - comparison result
59
+ */
60
+ function ascending(a, b)
61
+ {
62
+ return a < b ? -1 : a > b ? 1 : 0;
63
+ }
64
+
65
+ /**
66
+ * sort helper to sort array elements in descending order
67
+ *
68
+ * @param {mixed} a - an item to compare
69
+ * @param {mixed} b - an item to compare
70
+ * @returns {number} - comparison result
71
+ */
72
+ function descending(a, b)
73
+ {
74
+ return -1 * ascending(a, b);
75
+ }
backend/node_modules/asynckit/stream.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var inherits = require('util').inherits
2
+ , Readable = require('stream').Readable
3
+ , ReadableAsyncKit = require('./lib/readable_asynckit.js')
4
+ , ReadableParallel = require('./lib/readable_parallel.js')
5
+ , ReadableSerial = require('./lib/readable_serial.js')
6
+ , ReadableSerialOrdered = require('./lib/readable_serial_ordered.js')
7
+ ;
8
+
9
+ // API
10
+ module.exports =
11
+ {
12
+ parallel : ReadableParallel,
13
+ serial : ReadableSerial,
14
+ serialOrdered : ReadableSerialOrdered,
15
+ };
16
+
17
+ inherits(ReadableAsyncKit, Readable);
18
+
19
+ inherits(ReadableParallel, ReadableAsyncKit);
20
+ inherits(ReadableSerial, ReadableAsyncKit);
21
+ inherits(ReadableSerialOrdered, ReadableAsyncKit);
backend/node_modules/call-bind-apply-helpers/.eslintrc ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "root": true,
3
+
4
+ "extends": "@ljharb",
5
+
6
+ "rules": {
7
+ "func-name-matching": 0,
8
+ "id-length": 0,
9
+ "new-cap": [2, {
10
+ "capIsNewExceptions": [
11
+ "GetIntrinsic",
12
+ ],
13
+ }],
14
+ "no-extra-parens": 0,
15
+ "no-magic-numbers": 0,
16
+ },
17
+ }
backend/node_modules/call-bind-apply-helpers/.github/FUNDING.yml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # These are supported funding model platforms
2
+
3
+ github: [ljharb]
4
+ patreon: # Replace with a single Patreon username
5
+ open_collective: # Replace with a single Open Collective username
6
+ ko_fi: # Replace with a single Ko-fi username
7
+ tidelift: npm/call-bind-apply-helpers
8
+ community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9
+ liberapay: # Replace with a single Liberapay username
10
+ issuehunt: # Replace with a single IssueHunt username
11
+ otechie: # Replace with a single Otechie username
12
+ custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
backend/node_modules/call-bind-apply-helpers/.nycrc ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "all": true,
3
+ "check-coverage": false,
4
+ "reporter": ["text-summary", "text", "html", "json"],
5
+ "exclude": [
6
+ "coverage",
7
+ "test"
8
+ ]
9
+ }
backend/node_modules/call-bind-apply-helpers/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [v1.0.2](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.1...v1.0.2) - 2025-02-12
9
+
10
+ ### Commits
11
+
12
+ - [types] improve inferred types [`e6f9586`](https://github.com/ljharb/call-bind-apply-helpers/commit/e6f95860a3c72879cb861a858cdfb8138fbedec1)
13
+ - [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`e43d540`](https://github.com/ljharb/call-bind-apply-helpers/commit/e43d5409f97543bfbb11f345d47d8ce4e066d8c1)
14
+
15
+ ## [v1.0.1](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.0...v1.0.1) - 2024-12-08
16
+
17
+ ### Commits
18
+
19
+ - [types] `reflectApply`: fix types [`4efc396`](https://github.com/ljharb/call-bind-apply-helpers/commit/4efc3965351a4f02cc55e836fa391d3d11ef2ef8)
20
+ - [Fix] `reflectApply`: oops, Reflect is not a function [`83cc739`](https://github.com/ljharb/call-bind-apply-helpers/commit/83cc7395de6b79b7730bdf092f1436f0b1263c75)
21
+ - [Dev Deps] update `@arethetypeswrong/cli` [`80bd5d3`](https://github.com/ljharb/call-bind-apply-helpers/commit/80bd5d3ae58b4f6b6995ce439dd5a1bcb178a940)
22
+
23
+ ## v1.0.0 - 2024-12-05
24
+
25
+ ### Commits
26
+
27
+ - Initial implementation, tests, readme [`7879629`](https://github.com/ljharb/call-bind-apply-helpers/commit/78796290f9b7430c9934d6f33d94ae9bc89fce04)
28
+ - Initial commit [`3f1dc16`](https://github.com/ljharb/call-bind-apply-helpers/commit/3f1dc164afc43285631b114a5f9dd9137b2b952f)
29
+ - npm init [`081df04`](https://github.com/ljharb/call-bind-apply-helpers/commit/081df048c312fcee400922026f6e97281200a603)
30
+ - Only apps should have lockfiles [`5b9ca0f`](https://github.com/ljharb/call-bind-apply-helpers/commit/5b9ca0fe8101ebfaf309c549caac4e0a017ed930)
backend/node_modules/call-bind-apply-helpers/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Jordan Harband
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
backend/node_modules/call-bind-apply-helpers/README.md ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # call-bind-apply-helpers <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
2
+
3
+ [![github actions][actions-image]][actions-url]
4
+ [![coverage][codecov-image]][codecov-url]
5
+ [![dependency status][deps-svg]][deps-url]
6
+ [![dev dependency status][dev-deps-svg]][dev-deps-url]
7
+ [![License][license-image]][license-url]
8
+ [![Downloads][downloads-image]][downloads-url]
9
+
10
+ [![npm badge][npm-badge-png]][package-url]
11
+
12
+ Helper functions around Function call/apply/bind, for use in `call-bind`.
13
+
14
+ The only packages that should likely ever use this package directly are `call-bind` and `get-intrinsic`.
15
+ Please use `call-bind` unless you have a very good reason not to.
16
+
17
+ ## Getting started
18
+
19
+ ```sh
20
+ npm install --save call-bind-apply-helpers
21
+ ```
22
+
23
+ ## Usage/Examples
24
+
25
+ ```js
26
+ const assert = require('assert');
27
+ const callBindBasic = require('call-bind-apply-helpers');
28
+
29
+ function f(a, b) {
30
+ assert.equal(this, 1);
31
+ assert.equal(a, 2);
32
+ assert.equal(b, 3);
33
+ assert.equal(arguments.length, 2);
34
+ }
35
+
36
+ const fBound = callBindBasic([f, 1]);
37
+
38
+ delete Function.prototype.call;
39
+ delete Function.prototype.bind;
40
+
41
+ fBound(2, 3);
42
+ ```
43
+
44
+ ## Tests
45
+
46
+ Clone the repo, `npm install`, and run `npm test`
47
+
48
+ [package-url]: https://npmjs.org/package/call-bind-apply-helpers
49
+ [npm-version-svg]: https://versionbadg.es/ljharb/call-bind-apply-helpers.svg
50
+ [deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers.svg
51
+ [deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers
52
+ [dev-deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers/dev-status.svg
53
+ [dev-deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers#info=devDependencies
54
+ [npm-badge-png]: https://nodei.co/npm/call-bind-apply-helpers.png?downloads=true&stars=true
55
+ [license-image]: https://img.shields.io/npm/l/call-bind-apply-helpers.svg
56
+ [license-url]: LICENSE
57
+ [downloads-image]: https://img.shields.io/npm/dm/call-bind-apply-helpers.svg
58
+ [downloads-url]: https://npm-stat.com/charts.html?package=call-bind-apply-helpers
59
+ [codecov-image]: https://codecov.io/gh/ljharb/call-bind-apply-helpers/branch/main/graphs/badge.svg
60
+ [codecov-url]: https://app.codecov.io/gh/ljharb/call-bind-apply-helpers/
61
+ [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bind-apply-helpers
62
+ [actions-url]: https://github.com/ljharb/call-bind-apply-helpers/actions
backend/node_modules/call-bind-apply-helpers/actualApply.d.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ export = Reflect.apply;
backend/node_modules/call-bind-apply-helpers/actualApply.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+
3
+ var bind = require('function-bind');
4
+
5
+ var $apply = require('./functionApply');
6
+ var $call = require('./functionCall');
7
+ var $reflectApply = require('./reflectApply');
8
+
9
+ /** @type {import('./actualApply')} */
10
+ module.exports = $reflectApply || bind.call($call, $apply);
backend/node_modules/call-bind-apply-helpers/applyBind.d.ts ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import actualApply from './actualApply';
2
+
3
+ type TupleSplitHead<T extends any[], N extends number> = T['length'] extends N
4
+ ? T
5
+ : T extends [...infer R, any]
6
+ ? TupleSplitHead<R, N>
7
+ : never
8
+
9
+ type TupleSplitTail<T, N extends number, O extends any[] = []> = O['length'] extends N
10
+ ? T
11
+ : T extends [infer F, ...infer R]
12
+ ? TupleSplitTail<[...R], N, [...O, F]>
13
+ : never
14
+
15
+ type TupleSplit<T extends any[], N extends number> = [TupleSplitHead<T, N>, TupleSplitTail<T, N>]
16
+
17
+ declare function applyBind(...args: TupleSplit<Parameters<typeof actualApply>, 2>[1]): ReturnType<typeof actualApply>;
18
+
19
+ export = applyBind;
backend/node_modules/call-bind-apply-helpers/applyBind.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+
3
+ var bind = require('function-bind');
4
+ var $apply = require('./functionApply');
5
+ var actualApply = require('./actualApply');
6
+
7
+ /** @type {import('./applyBind')} */
8
+ module.exports = function applyBind() {
9
+ return actualApply(bind, $apply, arguments);
10
+ };
backend/node_modules/call-bind-apply-helpers/functionApply.d.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ export = Function.prototype.apply;