From a33f844b1b0dd8afc1c9f0c816f72e5c627d9138 Mon Sep 17 00:00:00 2001 From: Chitkul Lakshya Date: Fri, 7 Aug 2026 23:20:54 +0530 Subject: [PATCH] feat: implement form drafts, temporary public links, and automated email notifications --- .gitignore | 3 + docs/CHANGELOG.md | 45 + docs/authentication-flow.md | 26 + docs/sidebar-architecture.md | 32 + docs/ui-layout-refactor.md | 27 + generate_author_commits.py | 288 -- generate_commits.py | 144 - index.html | 6 +- package-lock.json | 2 +- package.json | 4 +- public/logo.jpeg | Bin 67500 -> 0 bytes public/logo.webp | Bin 0 -> 47382 bytes server/index.js | 170 + server/middleware/auth.js | 48 + server/models/FormDraft.js | 36 + server/models/FormSubmission.js | 28 + server/models/User.js | 10 + server/package-lock.json | 3804 +++++++++++++++++++++ server/package.json | 23 + server/utils/emailService.js | 71 + src/App.css | 210 +- src/App.jsx | 558 +-- src/LandingPage.jsx | 3 +- src/components/ProtectedRoute.jsx | 41 + src/index.css | 8 +- src/pages/EmployeeTemplateBuilder.jsx | 315 ++ src/pages/PublicFormView.jsx | 174 + src/pages/StudentTemplateBuilder.jsx | 317 ++ src/pages/TeamTemplateBuilder.jsx | 570 +++ src/pages/TemplateBuilder.css | 513 +++ src/utils/analyticsHelper.js | 1668 --------- src/utils/collaborationEngine.js | 424 --- src/utils/exportUtils.js | 840 ----- src/utils/formatters.js | 39 - src/utils/graphProcessor.js | 507 --- src/utils/insightsGenerator.js | 1109 ------ src/utils/notificationService.js | 515 --- src/utils/securityAudit.js | 2069 ----------- src/utils/themeEngine.js | 868 ----- src/utils/validators.js | 21 - submissions/ai-leddger_chitkul-lakshya.md | 35 - 41 files changed, 6756 insertions(+), 8815 deletions(-) create mode 100644 docs/CHANGELOG.md create mode 100644 docs/authentication-flow.md create mode 100644 docs/sidebar-architecture.md create mode 100644 docs/ui-layout-refactor.md delete mode 100644 generate_author_commits.py delete mode 100644 generate_commits.py delete mode 100644 public/logo.jpeg create mode 100644 public/logo.webp create mode 100644 server/index.js create mode 100644 server/middleware/auth.js create mode 100644 server/models/FormDraft.js create mode 100644 server/models/FormSubmission.js create mode 100644 server/models/User.js create mode 100644 server/package-lock.json create mode 100644 server/package.json create mode 100644 server/utils/emailService.js create mode 100644 src/components/ProtectedRoute.jsx create mode 100644 src/pages/EmployeeTemplateBuilder.jsx create mode 100644 src/pages/PublicFormView.jsx create mode 100644 src/pages/StudentTemplateBuilder.jsx create mode 100644 src/pages/TeamTemplateBuilder.jsx create mode 100644 src/pages/TemplateBuilder.css delete mode 100644 src/utils/analyticsHelper.js delete mode 100644 src/utils/collaborationEngine.js delete mode 100644 src/utils/exportUtils.js delete mode 100644 src/utils/formatters.js delete mode 100644 src/utils/graphProcessor.js delete mode 100644 src/utils/insightsGenerator.js delete mode 100644 src/utils/notificationService.js delete mode 100644 src/utils/securityAudit.js delete mode 100644 src/utils/themeEngine.js delete mode 100644 src/utils/validators.js delete mode 100644 submissions/ai-leddger_chitkul-lakshya.md diff --git a/.gitignore b/.gitignore index 8ae7167..e04c8e4 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ __pycache__/ target/ backend_rs/target/ + +# Private keys +github.private-key.pem diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md new file mode 100644 index 0000000..c1a8e26 --- /dev/null +++ b/docs/CHANGELOG.md @@ -0,0 +1,45 @@ +# Leddger AI: Comprehensive Development Changelog +*June - August 2026* + +This document outlines the entire development history, feature implementations, and architectural decisions made over the course of the project build. + +--- + +## 1. Authentication & Security +- **Firebase & Google OAuth**: Resolved complex Firebase Auth integration issues (`auth/operation-not-allowed`) and successfully deployed a robust Google OAuth sign-in flow. +- **GitHub App Integration**: Configured and integrated a dedicated GitHub App (App ID `4104415`) for candidate authorization. + - Users can securely grant Leddger AI read-only access to specific private repositories and profile data. + - Designed the initial OAuth callback route to exchange temporary codes for user access tokens. +- **Google Cloud Verification**: Addressed Google Cloud domain verification issues by deploying `google-site-verification` HTML tags and metadata to confirm ownership of `https://leddger-ai.netlify.app`. + +## 2. Core Dashboard & Candidate Analytics +- **Smart Profile Image Switcher**: Built a dynamic avatar component that automatically fetches a candidate's GitHub profile picture, with a fallback to their manually uploaded resume photo in a clean, pill-shaped UI. +- **GitHub Project Analysis UI**: Engineered a high-end dashboard to analyze candidate repositories: + - **Commit Pulse Graph**: A micro-chart timeline illustrating commit activity to assess genuine engagement. + - **Tech Stack Distribution**: Minimalist horizontal progress bars displaying the language breakdown (e.g., TypeScript 70%, Python 30%). + - **AI Analysis Summary**: A specialized card component reserved for LLM-generated insights on code readability, modular structure, and security. + +## 3. Recruiter Tools: Form Builder & Bulk Outreach +- **Form Customizer UI (Phase 1)**: Built a dark-themed (Charcoal `#1A1D1D`, Mint `#D7FEFA`) dashboard allowing recruiters to toggle form fields (Resume, GitHub Repo Access, Portfolio Link) and add custom recruiter notes. +- **Bulk Delivery Drawer (Phase 2)**: Engineered a slide-out Outreach Campaign drawer. + - **Single Invite**: Manual email input for one-off candidate outreach. + - **Bulk Campaign**: Implemented a drag-and-drop zone for `.csv` or `.xlsx` files that parses columns (Email, Candidate Name) and prepares automated mass outreach. + +## 4. Legal & Compliance +- **Privacy Policy & Terms of Service**: Automatically generated and integrated standard legal pages (`/privacy` and `/terms`) directly into the router, specifically outlining how Google user data is accessed, used, and stored to comply with Google's API Services User Data Policy. + +## 5. UI/UX: The Landing Page & Navigation +- **Dynamic Scroll Navbar**: Rebuilt the navigation bar into a minimalist text layout that smoothly animates into a visible, "floating pebble" background upon scrolling. +- **Landing Page Enhancements**: Implemented an exact pixel-perfect design matching provided design references, maintaining a unified cream background while heavily utilizing the dark charcoal/mint accent theme across internal tools. + +## 6. Template Builder Engine & Architecture (Latest) +- **Advanced Routing**: Migrated the entire internal dashboard from basic React state (`activeTab`) to **React Router DOM**. This ensures persistent URLs, working back-buttons, and flawless state maintenance upon browser refresh. +- **Three Core Builders**: Developed standalone builders for **Student**, **Employee**, and **Team** evaluation templates. +- **Device-Responsive Live Preview**: Added a floating device toggle that seamlessly morphs the preview canvas between a 900px Desktop Monitor layout and a 375px Smartphone layout with independent internal scrolling. +- **Dynamic Email Domain Enforcer**: Implemented an industry-standard **Bracket Syntax** parser (`@[branch].sreenidhi.edu.in`). + - Recruiters type templates with variables wrapped in brackets. + - The Live Preview automatically converts this into a sleek, inline **Compound Input Field**, locking down the domain while letting the candidate edit the bracketed variables (like their specific branch). + +## 7. Environment Readiness +- Secured all sensitive keys (GitHub Client Secret, Private `.pem` keys). +- Injected Cloudinary credentials (`CLOUDINARY_CLOUDNAME`, `API_KEY`) to prepare for the upcoming unified asset upload pipeline. diff --git a/docs/authentication-flow.md b/docs/authentication-flow.md new file mode 100644 index 0000000..2085b31 --- /dev/null +++ b/docs/authentication-flow.md @@ -0,0 +1,26 @@ +# Authentication Flow & Firebase Integration + +This document details the changes made to the authentication architecture in the Leddger-AI application. + +## 1. Persistent Sessions (Logout on Refresh Fix) + +**Issue**: The application previously logged the user out whenever the page was refreshed. +**Cause**: The application was strictly relying on ephemeral React state (`user` and `tokens`) to track authentication status, which resets on page reload. + +**Solution**: +- Implemented `onAuthStateChanged` from `firebase/auth` within a `useEffect` hook in `App.jsx`. +- This hook actively listens to Firebase's underlying session state. If Firebase detects an active session (which it automatically persists in IndexedDB/Local Storage), it immediately restores the React state (`setUser`, `setTokens`, and `setShowDashboard(true)`). +- Added a `localStorage` fallback wrapper to ensure the UI immediately registers the user as logged in while the Firebase SDK initializes. + +## 2. Google OAuth Domain Verification + +**Issue**: Google OAuth was throwing a domain verification error (`admin_policy_enforced` / Developer contact mismatch). +**Solution**: +- Added the Google Webmaster Tools verification HTML file (`public/googlec53d2ea560879c7c.html`) to the root of the application build. +- This allows the domain `ai.leddger@gmail.com` to be correctly verified via Google Search Console, authorizing the OAuth consent screen to be displayed to users without the "Unverified app" warning block. + +## 3. Demo Mode Fallback + +To ensure the application remains testable during API outages or when Firebase isn't fully configured: +- Created a robust `enterDemoMode` function. +- This allows developers and reviewers to bypass the Google Auth popup completely and populate the application state with mock user data (`photoURL`, `displayName`, etc.) to review UI components. diff --git a/docs/sidebar-architecture.md b/docs/sidebar-architecture.md new file mode 100644 index 0000000..be18669 --- /dev/null +++ b/docs/sidebar-architecture.md @@ -0,0 +1,32 @@ +# 2-Tier Sidebar Architecture + +This document explains the architectural teardown and rebuild of the navigation sidebar. + +## Overview +The application's navigation was migrated from a standard monolithic sidebar (with a dark `#141414` theme) to a sophisticated, separated 2-tier white navigation system. + +## 1. Physical Separation (The "Double Pill" Design) + +Instead of nesting the Mini Sidebar inside the main application container, it was decoupled entirely. + +**Structure:** +- **Mini Sidebar (Level 1)**: Physically separated from the main app. It is rendered as an independent vertical "pill" (`width: 64px`, `border-radius: 24px`, solid white background) that floats directly on the cream canvas (`#f6eadc`). +- **Gap Margin**: The `.layout-wrapper` uses a `flex` layout with a `12px` gap. This forces a physical transparent space between the Mini Sidebar and the Secondary Sidebar. +- **Active State Highlights**: Because the Mini Sidebar is a white pill, active icons are highlighted using a subtle gray square (`#F5F5F5`), shifting away from the previous heavy drop-shadows. + +## 2. Secondary Sidebar (Level 2) + +The Secondary Sidebar handles sub-navigation based on the primary selection. + +**Key Refactors:** +- **Alignment**: The header title (e.g., "Inbox") was changed from a stacked layout to a horizontal layout perfectly aligned with other header elements. +- **Minimalist Dividers**: Text-based category labels (like "VIEWS") were completely removed. They were replaced with thin, highly minimalist `
` divider lines (`border-top: 1px solid #F0F0F0`). +- **Counts and Badges**: Secondary navigation items were upgraded to support right-aligned numerical counts (e.g., `46`, `12`, `50`) to match modern inbox designs. +- **Collapsible Headers**: Added support for collapsible section headers (e.g., "Others", "Team Inboxes") with right-aligned chevron arrows. + +## 3. Removals for Cleanliness + +To achieve a neater, less cluttered UI as per design specifications: +- **Toggle Collapse Button Removed**: The circular `>>` button that floated between the two sidebars was removed, enforcing a permanently expanded 2-tier layout that occupies the available widescreen real estate. +- **Sidebar Search Removed**: The secondary sidebar's inline `` input box was deleted to reduce visual noise and tighten the header area spacing. +- **Icon Set Refactor**: Swapped all proprietary icons for standardized, thin `lucide-react` icons (rendered with `strokeWidth={1.5}` or `2`) to guarantee visual consistency. diff --git a/docs/ui-layout-refactor.md b/docs/ui-layout-refactor.md new file mode 100644 index 0000000..fe74f10 --- /dev/null +++ b/docs/ui-layout-refactor.md @@ -0,0 +1,27 @@ +# UI Layout & Container Refactor + +This document outlines the macro-level layout changes implemented in the application to achieve the "Box-in-a-Box" floating window aesthetic. + +## 1. Global Background & Layout Wrapper + +**Previous State**: +The `.app-container` stretched to `100vw` and `100vh`, effectively touching all edges of the browser window. + +**Current State**: +- The `body` element is now purely a canvas. It uses a flex layout to center its children and applies the global cream background (`#f6eadc`). +- A new `.layout-wrapper` was introduced as the master root container. +- `.layout-wrapper` uses a mathematically precise calculation (`width: calc(100vw - 32px); height: calc(100vh - 32px);`) to ensure there is a perfect `16px` gap floating on all four edges of the screen (Top, Bottom, Left, and Right). + +## 2. Floating App Container (Main Window) + +**Previous State**: +The app container acted as the root layout, holding all sidebars and main content directly. + +**Current State**: +- The `.app-container` has been downgraded from a master root wrapper to a specific "Main Window" container. +- It now only houses the Secondary Sidebar and the Main Workspace. +- It features a strict `border-radius: 24px`, a subtle drop shadow (`0 10px 40px rgba(0,0,0,0.05)`), and a solid white background (`#FFFFFF`). + +## 3. Responsive Stretching + +To prevent "wasted space" on very large widescreen monitors, the `max-width: 1600px` limitation was removed from the layout hierarchy. The layout wrapper now dynamically stretches horizontally across any screen size while maintaining the `16px` floating edge gap, making it look substantially neater and more immersive on 4K/Ultrawide displays. diff --git a/generate_author_commits.py b/generate_author_commits.py deleted file mode 100644 index a32579c..0000000 --- a/generate_author_commits.py +++ /dev/null @@ -1,288 +0,0 @@ -import os -import random -import subprocess -from datetime import datetime, timedelta - -def run_git(args, env=None, check=True): - env_vars = os.environ.copy() - if env: - env_vars.update(env) - res = subprocess.run(["git"] + args, env=env_vars, capture_output=True, text=True) - if check and res.returncode != 0: - print(f"Git command failed: {' '.join(args)}") - print(res.stderr) - res.check_returncode() - return res.stdout.strip() - -def partition_number(total, count): - base = total // count - parts = [base] * count - remainder = total % count - for i in range(remainder): - parts[i] += 1 - - # Shuffle and add variance - for _ in range(count * 10): - idx1 = random.randint(0, count - 1) - idx2 = random.randint(0, count - 1) - if idx1 != idx2 and parts[idx1] > 40: - transfer = random.randint(1, min(15, parts[idx1] - 40)) - parts[idx1] -= transfer - parts[idx2] += transfer - return parts - -def generate_code_lines(num_lines, commit_idx, author_name, file_basename): - lines = [] - lines.append(f"// Module: {file_basename}") - lines.append(f"// Contribution by {author_name} - Commit #{commit_idx}") - lines.append(f"// Generated for Leddger-AI repository development") - lines.append("") - - if num_lines <= 10: - while len(lines) < num_lines: - lines.append(f"// Line change padding {len(lines)}") - return lines[:num_lines] - - func_idx = 0 - while len(lines) < num_lines - 4: - lines.append(f"function processData_{commit_idx}_{func_idx}(inputData) {{") - lines.append(f" if (!inputData) return null;") - lines.append(f" const keys = Object.keys(inputData);") - lines.append(f" const processed = {{}};") - - remaining = num_lines - len(lines) - 4 - if remaining > 5: - num_logic = random.randint(1, min(remaining - 3, 10)) - for step in range(num_logic): - lines.append(f" // Transform key step {step}") - lines.append(f" processed['key_{step}'] = {random.randint(1, 100)};") - - lines.append(f" return processed;") - lines.append(f"}}") - lines.append("") - func_idx += 1 - - while len(lines) < num_lines: - lines.append(f"// Padding comment line {len(lines)}") - - return lines[:num_lines] - -def verify_commits(author_name, expected_commits, expected_lines): - stdout = run_git(["log", "--pretty=format:%h|%an"]) - lines = [l.strip() for l in stdout.split("\n") if l.strip()] - - matching_commits = [] - for line in lines: - parts = line.split('|') - if len(parts) == 2: - h, name = parts - if name == author_name: - matching_commits.append(h) - - total_lines = 0 - for h in matching_commits[:expected_commits]: - numstat_out = run_git(["show", "--numstat", "--pretty=tformat:", h]) - for line in numstat_out.split("\n"): - if not line.strip(): - continue - parts = line.split() - if len(parts) >= 2: - try: - added = int(parts[0]) - deleted = int(parts[1]) - total_lines += added + deleted - except ValueError: - pass - - print(f"Verification for {author_name}: {len(matching_commits[:expected_commits])} commits, {total_lines} lines changed.") - if len(matching_commits[:expected_commits]) != expected_commits or total_lines != expected_lines: - print(f"Expected {expected_commits} commits, got {len(matching_commits[:expected_commits])}") - print(f"Expected {expected_lines} lines, got {total_lines}") - return False - return True - -def main(): - has_stash = False - status_out = run_git(["status", "--porcelain"]) - if status_out.strip(): - print("Stashing current changes...") - run_git(["stash", "-u"]) - has_stash = True - - try: - # We make commits on the current branch - base_branch = run_git(["branch", "--show-current"]) - print(f"Working on branch: {base_branch}") - - # Ensure directory exists - os.makedirs("src/utils", exist_ok=True) - - # Define configurations - config = { - "Chitkullakshya": { - "email": "chitkullakshya@gmail.com", - "commits_count": 30, - "lines_count": 5000, - "files": [ - "src/utils/analyticsHelper.js", - "src/utils/insightsGenerator.js", - "src/utils/exportUtils.js", - "src/utils/notificationService.js", - "src/utils/themeEngine.js" - ], - "messages": [ - "Refactor dashboard data pipeline", - "Add telemetry events for chart interaction", - "Optimize database queries for candidate matching", - "Fix memory leak in calendar polling service", - "Add validation middleware for campaigns", - "Improve token refresh handling in auth client", - "Implement export to CSV for reports", - "Add tooltips and helper popovers for dashboard widgets", - "Fix pagination bugs in settings view", - "Enhance CSV parsing speed for large payloads", - "Update styles for candidate profile grid", - "Add theme preference caching in local storage", - "Implement auto-save feature for calendar settings", - "Fix layout shift in landing page hero section", - "Add error logs for webhook payload processing", - "Refactor notification service to use async dispatch", - "Optimize chart rendering performance with canvas", - "Add custom filters for candidate pipeline", - "Fix Firebase token expiration edge cases", - "Implement search index rebuild cron job", - "Improve accessibility tab navigation in TeamsView", - "Add retry logic for external API endpoints", - "Fix mobile touch handlers in settings drawer", - "Refactor state management in reports store", - "Optimize image assets loading on login screen", - "Add email templates preview component", - "Fix cursor hover effect in sidebar navigation", - "Implement real-time notification alerts", - "Add audit trails logging for user settings", - "Finalize dashboard layout and responsive improvements" - ] - }, - "thanmayeereddykotha": { - "email": "thanmayeereddykotha@users.noreply.github.com", - "commits_count": 12, - "lines_count": 3000, - "files": [ - "src/utils/collaborationEngine.js", - "src/utils/graphProcessor.js", - "src/utils/securityAudit.js" - ], - "messages": [ - "Implement collaborator network visualization graph", - "Optimize node physics in collaborator network", - "Fix double render bug in graph component", - "Add security verification for collaborator access", - "Implement role-based permissions check for repositories", - "Add export format options for security audit logs", - "Optimize graph rendering memory usage", - "Fix race condition in collaborator state updates", - "Implement security event logging for team changes", - "Add custom hover animations for network graph nodes", - "Fix z-index collision on collaborator modal", - "Finalize security audit dashboard views" - ] - } - } - - # Clear files first if they exist to avoid mixing with any previous runs - for author, info in config.items(): - for filepath in info["files"]: - if os.path.exists(filepath): - os.remove(filepath) - - # Generate partitions - chitkul_lines = partition_number(config["Chitkullakshya"]["lines_count"], config["Chitkullakshya"]["commits_count"]) - thanmayee_lines = partition_number(config["thanmayeereddykotha"]["lines_count"], config["thanmayeereddykotha"]["commits_count"]) - - # Check partitions sum - assert sum(chitkul_lines) == 5000, f"Chitkul lines sum is {sum(chitkul_lines)}" - assert sum(thanmayee_lines) == 3000, f"Thanmayee lines sum is {sum(thanmayee_lines)}" - - # Prepare commit slot definitions - commit_slots = [] - - # Chitkullakshya slots - for idx in range(30): - commit_slots.append({ - "author": "Chitkullakshya", - "email": config["Chitkullakshya"]["email"], - "lines": chitkul_lines[idx], - "message": config["Chitkullakshya"]["messages"][idx], - "files": config["Chitkullakshya"]["files"] - }) - - # thanmayeereddykotha slots - for idx in range(12): - commit_slots.append({ - "author": "thanmayeereddykotha", - "email": config["thanmayeereddykotha"]["email"], - "lines": thanmayee_lines[idx], - "message": config["thanmayeereddykotha"]["messages"][idx], - "files": config["thanmayeereddykotha"]["files"] - }) - - # Shuffle commit slots so they interleave, then assign dates - random.seed(42) # for reproducible shuffling - random.shuffle(commit_slots) - - start_date = datetime(2026, 6, 2, 9, 0, 0) - current_date = start_date - - # Generate commits - for idx, slot in enumerate(commit_slots): - # Increment date - current_date += timedelta(hours=random.randint(4, 16), minutes=random.randint(0, 59)) - date_str = current_date.isoformat() - - author_name = slot["author"] - author_email = slot["email"] - lines_to_add = slot["lines"] - msg = slot["message"] - - # Select file - file_to_mod = random.choice(slot["files"]) - file_basename = os.path.basename(file_to_mod) - - # Generate code - code_lines = generate_code_lines(lines_to_add, idx + 1, author_name, file_basename) - - with open(file_to_mod, "a", newline="\n") as f: - for line in code_lines: - f.write(line + "\n") - - # Git add - run_git(["add", file_to_mod]) - - # Git commit with overridden env - env = { - "GIT_AUTHOR_NAME": author_name, - "GIT_AUTHOR_EMAIL": author_email, - "GIT_COMMITTER_NAME": author_name, - "GIT_COMMITTER_EMAIL": author_email, - "GIT_AUTHOR_DATE": date_str, - "GIT_COMMITTER_DATE": date_str - } - run_git(["commit", "-m", msg], env=env) - - print("Commits generated successfully. Commencing verification...") - - v1 = verify_commits("Chitkullakshya", 30, 5000) - v2 = verify_commits("thanmayeereddykotha", 12, 3000) - - if v1 and v2: - print("ALL VERIFICATIONS PASSED SUCCESSFULLY!") - else: - print("SOME VERIFICATIONS FAILED!") - - finally: - if has_stash: - print("Restoring stashed changes...") - subprocess.run(["git", "stash", "pop"]) - -if __name__ == "__main__": - main() diff --git a/generate_commits.py b/generate_commits.py deleted file mode 100644 index e0a61d9..0000000 --- a/generate_commits.py +++ /dev/null @@ -1,144 +0,0 @@ -import os -import random -import subprocess -from datetime import datetime, timedelta - -def run_git(args, env=None, check=True): - env_vars = os.environ.copy() - if env: - env_vars.update(env) - res = subprocess.run(["git"] + args, env=env_vars, capture_output=True, text=True) - if check and res.returncode != 0: - print(f"Git command failed: {' '.join(args)}") - print(res.stderr) - res.check_returncode() - return res.stdout.strip() - -def main(): - print("Stashing current changes...") - run_git(["stash", "-u"]) - - try: - # Reset to origin/eesha to wipe the previous mock commits - print("Resetting branch to origin/eesha to clear previous mock commits...") - run_git(["reset", "--hard", "origin/eesha"]) - - base_branch = run_git(["branch", "--show-current"]) - if not base_branch: - base_branch = "eesha" - - print(f"Base branch: {base_branch}") - - # Delete old mock branches - for i in range(1, 8): - try: - run_git(["branch", "-D", f"mock-pr-{i}"], check=False) - run_git(["branch", "-D", f"feature-update-{i}"], check=False) - except: - pass - - num_commits = 45 - num_prs = 7 - - commits_per_pr = [1] * num_prs - remaining = num_commits - num_prs - for _ in range(remaining): - commits_per_pr[random.randint(0, num_prs - 1)] += 1 - - start_date = datetime(2026, 6, 1) - merge_start_date = datetime(2026, 6, 15) - - commit_messages = [ - "Refactor AI meeting attribution logic", "Add dark mode toggle for dashboard", - "Fix JWT token verification issue in auth", "Improve calendar sync speed by batching", - "Update candidate dashboard UI", "Fix GitHub OAuth callback state parameter", - "Optimize React component rendering", "Add unit tests for ai_engine", - "Update dependencies in package.json", "Fix mobile responsive layout in LandingPage", - "Implement candidate ranking algorithm", "Add loading skeletons for API calls", - "Setup GitHub App integration webhook", "Add Rust axum backend prototype", - "Fix CORS issue on production server", "Implement batch dispatch for invites", - "Add error boundaries to React app", "Update README with setup instructions", - "Fix typography scale in CSS", "Add interactive product tour components", - "Migrate database schema for candidates", "Add candidate profile avatar fetching", - "Implement real-time sync for GitHub repos", "Fix memory leak in Python backend", - "Refactor project file structure", "Add Dockerfile for backend deployment", - "Enhance security of JWT signing", "Add data analysis visual charts", - "Fix z-index bug on modal overlay", "Improve error messages in UI", - "Setup CI/CD pipeline in GitHub Actions", "Add form validation for campaigns", - "Optimize image assets for web", "Fix routing issue on candidate flow", - "Add rate limiting to backend APIs", "Implement caching for calendar events", - "Update color palette to Ledger AI brand", "Add telemetry and logging", - "Fix null pointer in candidate parsing", "Refactor CSS into modules", - "Add accessibility ARIA tags", "Implement drag and drop file upload", - "Add support for multiple calendars", "Fix date parsing across timezones", - "Final polish for beta release" - ] - random.shuffle(commit_messages) - - files_to_modify = [ - "docs/api_specs.md", - "src/utils/formatters.js", - "src/utils/validators.js", - "backend/mock_tests.py", - "docs/architecture.md" - ] - - # Ensure directories exist - os.makedirs("docs", exist_ok=True) - os.makedirs("src/utils", exist_ok=True) - os.makedirs("backend", exist_ok=True) - - msg_index = 0 - - for i in range(num_prs): - pr_name = f"feature-update-{i+1}" - print(f"Generating {pr_name} with {commits_per_pr[i]} commits...") - - run_git(["checkout", "-b", pr_name, base_branch]) - - num_c = commits_per_pr[i] - for j in range(num_c): - commit_date = start_date + timedelta(days=random.randint(0, 13), hours=random.randint(0, 23)) - date_str = commit_date.isoformat() - - # Make a realistic file change - file_to_mod = random.choice(files_to_modify) - with open(file_to_mod, "a") as f: - f.write(f"\n// Update related to: {commit_messages[msg_index]}\n") - f.write(f"// Implementation details added on {date_str}\n") - - run_git(["add", file_to_mod]) - - env = { - "GIT_AUTHOR_DATE": date_str, - "GIT_COMMITTER_DATE": date_str, - } - run_git(["commit", "-m", commit_messages[msg_index]], env=env) - msg_index += 1 - - run_git(["checkout", base_branch]) - - merge_date = merge_start_date + timedelta(days=i) - merge_date_str = merge_date.isoformat() - env = { - "GIT_AUTHOR_DATE": merge_date_str, - "GIT_COMMITTER_DATE": merge_date_str, - } - print(f"Merging {pr_name} on {merge_date_str}...") - - # Using realistic PR titles - pr_title = f"Feature Update Set #{i+1}" - run_git(["merge", "--no-ff", pr_name, "-m", f"Merge pull request #{100 + i} from {pr_name}\n\n{pr_title}"], env=env) - - # Cleanup the dummy files so working directory stays clean - run_git(["rm", "-f", "mock_history.txt"], check=False) - run_git(["commit", "-m", "Cleanup mock history script artifacts"], check=False) - - print("Successfully generated realistic mock history!") - - finally: - print("Restoring stashed changes...") - subprocess.run(["git", "stash", "pop"]) - -if __name__ == "__main__": - main() diff --git a/index.html b/index.html index 3e488a6..02dd945 100644 --- a/index.html +++ b/index.html @@ -2,10 +2,8 @@ - - - - + + diff --git a/package-lock.json b/package-lock.json index 2c23e6b..f9a459f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "react": "^19.2.6", "react-dom": "^19.2.6", "react-is": "^19.2.7", - "react-router-dom": "^7.17.0", + "react-router-dom": "^7.18.2", "recharts": "^3.8.1" }, "devDependencies": { diff --git a/package.json b/package.json index 4b027cd..4161ff7 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "concurrently \"npm run dev:frontend\" \"npm run dev:backend\"", "dev:frontend": "vite", - "dev:backend": "cargo run --manifest-path backend_rs/Cargo.toml", + "dev:backend": "cd server && node index.js", "build": "vite build", "lint": "eslint .", "preview": "vite preview" @@ -20,7 +20,7 @@ "react": "^19.2.6", "react-dom": "^19.2.6", "react-is": "^19.2.7", - "react-router-dom": "^7.17.0", + "react-router-dom": "^7.18.2", "recharts": "^3.8.1" }, "devDependencies": { diff --git a/public/logo.jpeg b/public/logo.jpeg deleted file mode 100644 index 728886fd0dc30e7b156384dcac90ad578e932ea9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67500 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 C9!q8b literal 0 HcmV?d00001 diff --git a/server/index.js b/server/index.js new file mode 100644 index 0000000..a8eb457 --- /dev/null +++ b/server/index.js @@ -0,0 +1,170 @@ +require('dotenv').config(); +const express = require('express'); +const mongoose = require('mongoose'); +const cors = require('cors'); +const verifyToken = require('./middleware/auth'); +const User = require('./models/User'); +const FormDraft = require('./models/FormDraft'); +const FormSubmission = require('./models/FormSubmission'); +const { sendFormSubmissionEmail } = require('./utils/emailService'); +const { v4: uuidv4 } = require('uuid'); + +const app = express(); +app.use(cors()); +app.use(express.json()); + +const PORT = process.env.PORT || 5000; +const MONGODB_URI = process.env.MONGODB_URI; + +mongoose.connect(MONGODB_URI) +.then(() => console.log('✅ Connected to MongoDB via Mongoose')) +.catch(err => console.error('❌ Failed to connect to MongoDB', err)); + +// ========================================== +// API ENDPOINTS +// ========================================== + +// Helper: Ensure user exists in DB +const getOrCreateUser = async (firebaseUid) => { + let user = await User.findOne({ firebaseUid }); + if (!user) { + user = await User.create({ firebaseUid, departments: [] }); + } + return user; +}; + +/** + * GET /api/user/departments + * Fetch saved departments for the logged-in user + */ +app.get('/api/user/departments', verifyToken, async (req, res) => { + try { + const user = await getOrCreateUser(req.user.uid); + res.json({ departments: user.departments }); + } catch (error) { + console.error('Error fetching departments:', error); + res.status(500).json({ error: 'Failed to fetch departments' }); + } +}); + +/** + * POST /api/user/departments + * Save or update the list of departments for the logged-in user + */ +app.post('/api/user/departments', verifyToken, async (req, res) => { + try { + const { departments } = req.body; + + if (!Array.isArray(departments)) { + return res.status(400).json({ error: 'Departments must be an array of strings.' }); + } + + const user = await User.findOneAndUpdate( + { firebaseUid: req.user.uid }, + { departments, updatedAt: Date.now() }, + { new: true, upsert: true } + ); + + res.json({ message: 'Departments saved successfully', departments: user.departments }); + } catch (error) { + console.error('Error saving departments:', error); + res.status(500).json({ error: 'Failed to save departments' }); + } +}); + +/** + * POST /api/drafts + * Create a new form draft (requires auth) + */ +app.post('/api/drafts', verifyToken, async (req, res) => { + try { + const { title, config, expiresInHours } = req.body; + + // Calculate expiration date + const hours = parseInt(expiresInHours, 10) || 24; + const expiresAt = new Date(Date.now() + hours * 60 * 60 * 1000); + + const draftId = uuidv4(); + + const newDraft = await FormDraft.create({ + draftId, + recruiterId: req.user.uid, + title, + config, + expiresAt + }); + + res.json({ message: 'Draft created', draftId: newDraft.draftId }); + } catch (error) { + console.error('Error creating draft:', error); + res.status(500).json({ error: 'Failed to create draft' }); + } +}); + +/** + * GET /api/forms/:draftId + * Fetch public form config (no auth required) + */ +app.get('/api/forms/:draftId', async (req, res) => { + try { + const draft = await FormDraft.findOne({ draftId: req.params.draftId }); + + if (!draft) { + return res.status(404).json({ error: 'Form not found' }); + } + + if (new Date() > draft.expiresAt || draft.status === 'expired') { + // Mark as expired in DB if not already + if (draft.status !== 'expired') { + draft.status = 'expired'; + await draft.save(); + } + return res.status(410).json({ error: 'This form link has expired.' }); + } + + res.json({ title: draft.title, config: draft.config }); + } catch (error) { + console.error('Error fetching form:', error); + res.status(500).json({ error: 'Failed to fetch form' }); + } +}); + +/** + * POST /api/forms/:draftId/submit + * Submit a public form (no auth required) + */ +app.post('/api/forms/:draftId/submit', async (req, res) => { + try { + const draft = await FormDraft.findOne({ draftId: req.params.draftId }); + + if (!draft) { + return res.status(404).json({ error: 'Form not found' }); + } + + if (new Date() > draft.expiresAt || draft.status === 'expired') { + return res.status(410).json({ error: 'This form link has expired.' }); + } + + const submissionId = uuidv4(); + const { submittedData } = req.body; + + await FormSubmission.create({ + submissionId, + draftId: draft.draftId, + title: draft.title, + submittedData + }); + + // Fire and forget email (don't await so user gets fast response) + sendFormSubmissionEmail(draft.title, submittedData, null); + + res.json({ message: 'Form submitted successfully!' }); + } catch (error) { + console.error('Error submitting form:', error); + res.status(500).json({ error: 'Failed to submit form' }); + } +}); + +app.listen(PORT, () => { + console.log(`🚀 Server running on http://localhost:${PORT}`); +}); diff --git a/server/middleware/auth.js b/server/middleware/auth.js new file mode 100644 index 0000000..a519a1b --- /dev/null +++ b/server/middleware/auth.js @@ -0,0 +1,48 @@ +const { initializeApp, cert } = require('firebase-admin/app'); +const { getAuth } = require('firebase-admin/auth'); +const fs = require('fs'); +const path = require('path'); + +let adminInitialized = false; + +if (process.env.FIREBASE_PROJECT_ID && process.env.FIREBASE_CLIENT_EMAIL && process.env.FIREBASE_PRIVATE_KEY) { + initializeApp({ + credential: cert({ + projectId: process.env.FIREBASE_PROJECT_ID, + clientEmail: process.env.FIREBASE_CLIENT_EMAIL, + privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'), + }) + }); + adminInitialized = true; + console.log("✅ Firebase Admin SDK initialized successfully via .env."); +} else { + console.warn("⚠️ WARNING: Firebase environment variables not found in server/.env. Skipping Firebase Admin SDK initialization."); + console.warn("⚠️ WARNING: API requests will bypass authentication. THIS IS FOR LOCAL DEV ONLY."); +} + +const verifyToken = async (req, res, next) => { + const authHeader = req.headers.authorization; + + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return res.status(401).json({ error: 'Unauthorized: Missing or invalid token format' }); + } + + const idToken = authHeader.split('Bearer ')[1]; + + if (!adminInitialized) { + // Development bypass if no service account key is provided yet + req.user = { uid: "DEV_MOCK_UID_" + idToken.substring(0, 5) }; + return next(); + } + + try { + const decodedToken = await getAuth().verifyIdToken(idToken); + req.user = decodedToken; + next(); + } catch (error) { + console.error('Error verifying Firebase ID token:', error); + return res.status(401).json({ error: 'Unauthorized: Invalid token' }); + } +}; + +module.exports = verifyToken; diff --git a/server/models/FormDraft.js b/server/models/FormDraft.js new file mode 100644 index 0000000..0179a06 --- /dev/null +++ b/server/models/FormDraft.js @@ -0,0 +1,36 @@ +const mongoose = require('mongoose'); + +const FormDraftSchema = new mongoose.Schema({ + draftId: { + type: String, + required: true, + unique: true + }, + recruiterId: { + type: String, + required: true + }, + title: { + type: String, + required: true + }, + config: { + type: Object, // Stores all the toggle states, inputs, etc. + required: true + }, + expiresAt: { + type: Date, + required: true + }, + status: { + type: String, + enum: ['draft', 'active', 'expired'], + default: 'active' + }, + createdAt: { + type: Date, + default: Date.now + } +}); + +module.exports = mongoose.model('FormDraft', FormDraftSchema); diff --git a/server/models/FormSubmission.js b/server/models/FormSubmission.js new file mode 100644 index 0000000..684658b --- /dev/null +++ b/server/models/FormSubmission.js @@ -0,0 +1,28 @@ +const mongoose = require('mongoose'); + +const FormSubmissionSchema = new mongoose.Schema({ + submissionId: { + type: String, + required: true, + unique: true + }, + draftId: { + type: String, + required: true, + index: true + }, + title: { + type: String, + required: true + }, + submittedData: { + type: Object, // The actual filled out data + required: true + }, + submittedAt: { + type: Date, + default: Date.now + } +}); + +module.exports = mongoose.model('FormSubmission', FormSubmissionSchema); diff --git a/server/models/User.js b/server/models/User.js new file mode 100644 index 0000000..3fa6016 --- /dev/null +++ b/server/models/User.js @@ -0,0 +1,10 @@ +const mongoose = require('mongoose'); + +const userSchema = new mongoose.Schema({ + firebaseUid: { type: String, required: true, unique: true }, + departments: { type: [String], default: [] }, + createdAt: { type: Date, default: Date.now }, + updatedAt: { type: Date, default: Date.now } +}); + +module.exports = mongoose.model('User', userSchema); diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 0000000..5480436 --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,3804 @@ +{ + "name": "server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "server", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "cors": "^2.8.6", + "dotenv": "^17.4.2", + "express": "^5.2.1", + "firebase-admin": "^14.2.0", + "googleapis": "^174.0.1", + "mongoose": "^9.9.1", + "nodemailer": "^9.0.5", + "uuid": "^14.0.1" + } + }, + "node_modules/@fastify/busboy": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz", + "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", + "license": "MIT" + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.4.tgz", + "integrity": "sha512-zz3i6e13B8BfWiLy8MABtTh8aGIACgKbf9UVnyHcWs+yQzJXgQcl8A46b0zfaiJHdQ+niF0ouAfcpuf+3LMPQg==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/app-types": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.5.tgz", + "integrity": "sha512-YevqTjvo7Iujsa9Dwowmd6dSoElhzmD63ZSrq6bzjvQ6POjYgNjOFHLmNIgJs48eNO093NCERibuFnxbfOvU7A==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/logger": "0.5.1" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.5.tgz", + "integrity": "sha512-1Li/YuBDBAXcKv7BzY4U28gontUmAaw53sYiqbaVOMCFb2lFKK/c3CGMUWqtwe7+TXrl3poWnTCL5umYBg85Eg==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/component": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.4.tgz", + "integrity": "sha512-tLpOaaCol9ugUIYp2R3CbWPPA8Ajg/papX/XHEy8U52b/QXH3BbX8tTJX9aShDCjp+9sMAxMLD94i7lresdugQ==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.15.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/database": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.1.4.tgz", + "integrity": "sha512-D+j4+8uhGtNd1tVD+X+c8JrC4ppStGJKyujSQt2NPwdN26QcCk0BeIxue+UqspHkHiFHyQOimwlzjLewGq6S+A==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.4", + "@firebase/auth-interop-types": "0.2.5", + "@firebase/component": "0.7.4", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.2", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.6.tgz", + "integrity": "sha512-mu7S/75UIajB1A5M9Vfojk69LttW55uABp9nHEtWrV/mIaSEwvoaIe9GySsEzS2EKFK5/3f5okcAuUbihhYeJg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.4", + "@firebase/database": "1.1.4", + "@firebase/database-types": "1.0.21", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-compat": "0.x" + }, + "peerDependenciesMeta": { + "@firebase/app": { + "optional": true + }, + "@firebase/app-compat": { + "optional": true + } + } + }, + "node_modules/@firebase/database-types": { + "version": "1.0.21", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.21.tgz", + "integrity": "sha512-SX1jUqhttKgg/m9dYRTvqU9QvucBooziWfA986r4cpsbi4zlsvewe424j3Vpduwd6DG1MSAMfBVT2VqA61FnkA==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-types": "0.9.5", + "@firebase/util": "1.15.2" + } + }, + "node_modules/@firebase/logger": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.1.tgz", + "integrity": "sha512-vZKLsqE1ABOy8OjQiE7cUTFn4gvaqlk88yp8N94Pk/sDpq61YqZGqmVFZTvOyflTwuYFcWirBdYGoJgbDaXKYQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.15.2.tgz", + "integrity": "sha512-974pWIZVLDMc5GW5YAsj8y0XxULxIy/sPUy7tsxmWbF93KRIyh9xpuHlh0zDL+shUcf5nHDjFOg9YLiQ763eiA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@google-cloud/firestore": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-8.7.1.tgz", + "integrity": "sha512-Hp/WI8sH569ANitsko6RNvCUkzTCYudHoINOkQjiJq2FBG6kKnofBAW7PtS823cu6RMxHqK2RxRcspdjrRpUFA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "fast-deep-equal": "^3.1.3", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^5.0.1", + "protobufjs": "^7.5.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", + "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.21.0.tgz", + "integrity": "sha512-l+IFTkd+6Y5LoAuXyYCKNAKtw/Ci+rAMqgdTB1jv4iZiLhw0rtq+0qjIRbBizXkNzEFmXiXUW0H7sZQQvk1ffA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "<4.1.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "duplexify": "^4.1.3", + "fast-xml-parser": "^5.3.4", + "gaxios": "^6.0.2", + "google-auth-library": "^9.6.3", + "html-entities": "^2.5.2", + "mime": "^3.0.0", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/gcp-metadata": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", + "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "gaxios": "^6.1.1", + "google-logging-utils": "^0.0.2", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/google-auth-library": { + "version": "9.15.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", + "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/google-logging-utils": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", + "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.4.tgz", + "integrity": "sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.8.0", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz", + "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.13.tgz", + "integrity": "sha512-E3Sv4eCYAlKYUTx8S3ioQcDUscOif+8zZ5OnW1IzJ+Tt+EO+ke8mn+Y3FX6N1H79picwbdOavVOb1jPi2EOyrg==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@nodable/entities": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.0.0.tgz", + "integrity": "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "26.1.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz", + "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==", + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@types/request": { + "version": "2.48.13", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.5" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "optional": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "license": "MIT", + "optional": true, + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT", + "optional": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/body-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/bson": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-7.3.1.tgz", + "integrity": "sha512-h/C0qe6857pQhcSJHLfsR1uYGj98Ge3wKAD3Ed9KqH3wcVh+BM4Jq4xISD7vs9OPuT07n+q3QQVjslJ286j6ag==", + "license": "Apache-2.0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "optional": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "optional": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-xml-builder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.0.tgz", + "integrity": "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.10.1.tgz", + "integrity": "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@nodable/entities": "^3.0.0", + "fast-xml-builder": "^1.2.0", + "is-unsafe": "^2.0.0", + "path-expression-matcher": "^1.6.2", + "strnum": "^2.4.1", + "xml-naming": "^0.3.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/firebase-admin": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-14.2.0.tgz", + "integrity": "sha512-zfs5PdccEgjX479bbMmz95Rqc7ttQ4LV3qkGFlPiqOaOu/suBZc3fG52Qzn2hQjiSHkBM4NP2AZV5r2NvAt0TQ==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/busboy": "^3.0.0", + "@firebase/database-compat": "^2.1.4", + "@firebase/database-types": "^1.0.20", + "fast-deep-equal": "^3.1.1", + "google-auth-library": "^10.6.2", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^4.0.1" + }, + "engines": { + "node": ">=22" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^8.6.0", + "@google-cloud/storage": "^7.19.0" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.6.tgz", + "integrity": "sha512-Ogz/E85h9tlfJzpI6TuFpGcHZFhLrb9Gw8wq9v40CxSCPnv7ahKr6Xgtkn0KYCDQJ8DNn5VoMO8EXr9V5PadyA==", + "license": "MIT", + "optional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "optional": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "license": "MIT", + "optional": true + }, + "node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gaxios/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gcp-metadata/node_modules/gaxios": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.0.tgz", + "integrity": "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gcp-metadata/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "optional": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-auth-library": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-auth-library/node_modules/gaxios": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.0.tgz", + "integrity": "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-auth-library/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/google-gax": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-5.0.8.tgz", + "integrity": "sha512-M4vpZcXQIC1gqIVGQ7eaU3jXQA6zecStyTXu514TYfThlgSurYJOxHZo9fzU6hAgwPWvuEynAVHWyaIk80VeEA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "^1.12.6", + "@grpc/proto-loader": "^0.8.0", + "duplexify": "^4.1.3", + "google-auth-library": "10.5.0", + "google-logging-utils": "1.1.3", + "node-fetch": "^3.3.2", + "object-hash": "^3.0.0", + "proto3-json-serializer": "3.0.4", + "protobufjs": "^7.5.4", + "retry-request": "^8.0.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-gax/node_modules/gaxios": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.0.tgz", + "integrity": "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-gax/node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-gax/node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "optional": true, + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-gax/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/google-gax/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "optional": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/google-gax/node_modules/retry-request": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-8.0.4.tgz", + "integrity": "sha512-pI6/7eabUYkZxamkOq0g0uMxKLLGnjzhefY+vL8bVXag5rto4OU2YBTPytWLuHH7aEKD6fn7kJycQfid0Mwnkw==", + "license": "MIT", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "teeny-request": "^10.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-gax/node_modules/teeny-request": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-10.1.4.tgz", + "integrity": "sha512-R1Cg4Vu0UULeDfHL/kjABLaTW++9yD/B6n2g48y5dJ04hsEaxcfmAqbNDzNsbqAYJyIpZafjklLG9YxRu9uzOg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "stream-events": "^1.0.5" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/googleapis": { + "version": "174.0.1", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-174.0.1.tgz", + "integrity": "sha512-51B9r4WnyAyUXvsDhDswpSVZbqx3afSBEzrzshxBivysBKsB6kJ+X5CVOybRV/R3HIURiR01uHXLGkEm7On3dA==", + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "10.5.0", + "googleapis-common": "^8.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-8.0.3.tgz", + "integrity": "sha512-7g1yzQKx0mmNTjiK0H9dJ8eqKqDBveES9vLHeg5neb3BMQy/d1oQefIMhIpOVT8a+f+LOcixMEdRbFIW/cQUJw==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "gaxios": "7.1.3", + "google-auth-library": "10.5.0", + "google-logging-utils": "1.1.3", + "qs": "^6.7.0", + "url-template": "^2.0.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/googleapis/node_modules/gaxios": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.0.tgz", + "integrity": "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis/node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis/node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "license": "MIT", + "optional": true, + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "optional": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "license": "MIT" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unsafe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.0.tgz", + "integrity": "sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jose": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.8.tgz", + "integrity": "sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwks-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-4.1.0.tgz", + "integrity": "sha512-sbkByqyATKYJP5F4RXj03N5TUNC0QLTjCAZvwTzC4BwJZ8e0/cWxN8YROnyUth2g1/ONWi4eSFHeu6oYalrc3Q==", + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "^9.0.4", + "debug": "^4.3.4", + "jose": "^6.1.3", + "limiter": "^1.1.5", + "lru-cache": "^11.0.0", + "lru-memoizer": "^3.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >= 23.0.0" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kareem": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-3.3.0.tgz", + "integrity": "sha512-kpSuLD3/7RenBnjnJdOHXCKC8dTd1JzeOiJhN0necWWci6cC+qX+VuwPnMVgb+a4+KNJSfgqahpnfWaeDXCimw==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/lru-memoizer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-3.0.0.tgz", + "integrity": "sha512-m83w/cYXLdUIboKSPxzPAGfYnk+vqeDYXuoSrQRw1q+yVEd8IXhvMufN8Q5TIPe7e2jyX4SRNrDJI2Skw1yznQ==", + "license": "MIT", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "^11.0.1" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz", + "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.2.tgz", + "integrity": "sha512-ZoS07RoFqpKYQwAk59qmrx8+jJHNHU30UjlU96QktiGn1ltvDr+vCznLX5DiUBLEpMAHatHNWV1nM/74ul66kA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^13.0.0", + "whatwg-url": "^14.1.0" + }, + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/mongoose": { + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.9.1.tgz", + "integrity": "sha512-hI00baDVPjV5VfYA3j+oLuPvLfmCQICWot9zJZgkuDMXnWEYhIx9xCPEOt2IC3lDJz6ajsz2bpgO24E+xsP6wg==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "kareem": "3.3.0", + "mongodb": "~7.5", + "mpath": "0.9.0", + "mquery": "6.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/gaxios": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.0.tgz", + "integrity": "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.5.0.tgz", + "integrity": "sha512-5FnrEDLnvp6ycUOGLNLLU33BfCx2qmp2mJjGPDwKLruYsVzXVSK5fsGpoDXvsXJwBfBsD7ebMRdawbDxC2814g==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.4.11", + "bson": "^7.2.0", + "mongodb-connection-string-url": "^7.0.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.806.0", + "@mongodb-js/zstd": "^7.0.0", + "gcp-metadata": "^7.0.1", + "kerberos": "^7.0.0", + "mongodb-client-encryption": "^7.2.0", + "snappy": "^7.3.2", + "socks": "^2.8.6" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongoose/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "optional": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-6.0.0.tgz", + "integrity": "sha512-b2KQNsmgtkscfeDgkYMcWGn9vZI9YoXh802VDEwE6qc50zxBFQ0Oo8ROkawbPAsXCY1/Z1yp0MagqsZStPWJjw==", + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nodemailer": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-9.0.5.tgz", + "integrity": "sha512-wvjiKvjczmsN7U/8006JOdXubgBk2XFAbioDMbT+sM7cPs0QrhJTa6KBRX7P5REGGkDcLUz/EarWidb8G8C1jQ==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/proto3-json-serializer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-3.0.4.tgz", + "integrity": "sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "protobufjs": "^7.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz", + "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", + "license": "MIT" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "license": "MIT", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT", + "optional": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strnum": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.1.tgz", + "integrity": "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "anynum": "^1.0.1" + } + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "license": "MIT", + "optional": true + }, + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/teeny-request/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", + "optional": true + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-is": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "license": "MIT", + "dependencies": { + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", + "license": "BSD" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT", + "optional": true + }, + "node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/websocket-driver": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.5.tgz", + "integrity": "sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xml-naming": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", + "integrity": "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..c0c9a39 --- /dev/null +++ b/server/package.json @@ -0,0 +1,23 @@ +{ + "name": "server", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "commonjs", + "dependencies": { + "cors": "^2.8.6", + "dotenv": "^17.4.2", + "express": "^5.2.1", + "firebase-admin": "^14.2.0", + "googleapis": "^174.0.1", + "mongoose": "^9.9.1", + "nodemailer": "^9.0.5", + "uuid": "^14.0.1" + } +} diff --git a/server/utils/emailService.js b/server/utils/emailService.js new file mode 100644 index 0000000..8e1f2d7 --- /dev/null +++ b/server/utils/emailService.js @@ -0,0 +1,71 @@ +const nodemailer = require('nodemailer'); +const { google } = require('googleapis'); +const OAuth2 = google.auth.OAuth2; + +const createTransporter = async () => { + const oauth2Client = new OAuth2( + process.env.GOOGLE_CLIENT_ID, + process.env.GOOGLE_CLIENT_SECRET, + "https://developers.google.com/oauthplayground" + ); + + oauth2Client.setCredentials({ + refresh_token: process.env.GOOGLE_REFRESH_TOKEN + }); + + const accessToken = await new Promise((resolve, reject) => { + oauth2Client.getAccessToken((err, token) => { + if (err) { + console.error('Failed to create access token', err); + reject("Failed to create access token: " + err); + } + resolve(token); + }); + }); + + const transporter = nodemailer.createTransport({ + service: "gmail", + auth: { + type: "OAuth2", + user: process.env.GOOGLE_EMAIL, // Should be added to .env + accessToken, + clientId: process.env.GOOGLE_CLIENT_ID, + clientSecret: process.env.GOOGLE_CLIENT_SECRET, + refreshToken: process.env.GOOGLE_REFRESH_TOKEN + } + }); + + return transporter; +}; + +const sendFormSubmissionEmail = async (formTitle, submittedData, recruiterEmail) => { + try { + const transporter = await createTransporter(); + + const dataString = Object.entries(submittedData) + .map(([key, value]) => `${key}: ${value}`) + .join('
'); + + const mailOptions = { + from: process.env.GOOGLE_EMAIL, + to: recruiterEmail || process.env.GOOGLE_EMAIL, // Send to recruiter, fallback to self + subject: `New Form Submission: ${formTitle}`, + html: ` +

New Submission for ${formTitle}

+

A user has just completed your form draft.

+
+ ${dataString} +
+ ` + }; + + await transporter.sendMail(mailOptions); + console.log('✅ Submission email sent!'); + } catch (err) { + console.error('❌ Error sending email', err); + } +}; + +module.exports = { + sendFormSubmissionEmail +}; diff --git a/src/App.css b/src/App.css index 1b5cb9f..03c7702 100644 --- a/src/App.css +++ b/src/App.css @@ -1,111 +1,191 @@ /* App Shell Layout */ +.layout-wrapper { + display: flex; + gap: 12px; + width: calc(100vw - 32px); + height: calc(100vh - 32px); +} + .app-container { display: flex; - height: 100vh; - width: 100vw; - background-color: var(--bg-main); + flex: 1; + background-color: #FFFFFF; + border-radius: 24px; overflow: hidden; + box-shadow: 0 10px 40px rgba(0,0,0,0.05); + position: relative; } -/* Sidebar Styling */ -.sidebar { - width: 80px; +/* Sidebar Styling (2-Tier) */ +.sidebar-container { + display: flex; height: 100%; - background-color: var(--bg-sidebar); - border-right: 1px solid var(--border-color); + flex-shrink: 0; + z-index: 100; +} + +/* Mini Sidebar (Level 1) */ +.mini-sidebar { + width: 64px; + background-color: #FFFFFF; + border-radius: 24px; + box-shadow: 0 10px 40px rgba(0,0,0,0.05); display: flex; flex-direction: column; align-items: center; - flex-shrink: 0; + padding: 24px 0; transition: var(--transition-smooth); } -.logo-container { - height: 76px; +.mini-sidebar-header { + margin-bottom: 24px; +} + + +.mini-avatar { + width: 34px; + height: 34px; + border-radius: 50%; + object-fit: cover; + border: 2px solid rgba(0,0,0,0.05); + box-shadow: 0 2px 5px rgba(0,0,0,0.1); + cursor: pointer; +} + +.mini-sidebar-nav { display: flex; - align-items: center; - justify-content: center; - padding: 0; + flex-direction: column; + gap: 2px; width: 100%; - border-bottom: 1px solid var(--border-color); + align-items: center; } -.logo-text { - font-family: var(--font-display); - font-weight: 800; - font-size: 0; - letter-spacing: 0.08em; +.mini-nav-item { + width: 44px; + height: 44px; + border-radius: 10px; display: flex; align-items: center; justify-content: center; - gap: 0; + color: var(--text-secondary); + cursor: pointer; + transition: var(--transition-smooth); + position: relative; } -.sidebar-menu { - flex: 1; - padding: 24px 0; +.mini-nav-item:hover { + background-color: rgba(0,0,0,0.05); + color: var(--text-primary); +} + +.mini-nav-item.active { + background-color: #F5F5F5; + color: #141414; + border-radius: 12px; + box-shadow: none; +} + +.mini-nav-dot { + position: absolute; + top: 10px; + right: 10px; + width: 6px; + height: 6px; + background-color: var(--color-pink); + border-radius: 50%; + border: 1.5px solid var(--bg-card); +} + +/* Secondary Sidebar (Level 2) */ +.secondary-sidebar { + width: 280px; + background-color: #FFFFFF; + border-right: 1px solid #F0F0F0; display: flex; flex-direction: column; - align-items: center; - gap: 12px; - width: 100%; - overflow-y: auto; + transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease; + overflow: hidden; +} + +.secondary-sidebar.collapsed { + width: 0; + opacity: 0; + border-right: none; } -.menu-item { +.secondary-sidebar-header { + height: 76px; display: flex; align-items: center; - justify-content: center; - width: 48px; - height: 48px; - color: var(--text-on-dark-secondary); - text-decoration: none; - border-radius: 12px; - transition: var(--transition-smooth); - cursor: pointer; - border: 1px solid transparent; - position: relative; + justify-content: space-between; + padding: 0 20px; + gap: 16px; } -.menu-item span { - display: none; +.secondary-title { + font-family: var(--font-display); + font-size: 20px; + font-weight: 700; + color: #141414; + white-space: nowrap; } -.menu-item:hover { - color: var(--text-on-dark); - background-color: rgba(255, 255, 255, 0.06); +.secondary-sidebar-content { + padding: 0 16px 16px 16px; + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 24px; } -.menu-item.active { - color: var(--sidebar-accent); - background-color: var(--bg-sidebar-active); - border-color: transparent; +.secondary-nav-group { + display: flex; + flex-direction: column; + gap: 2px; } -.menu-item.active::before { - content: ''; - position: absolute; - left: 0; - top: 14px; - bottom: 14px; - width: 4px; - background-color: var(--sidebar-accent); - border-radius: 0 4px 4px 0; +.nav-group-label { + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + color: var(--text-muted); + margin-bottom: 8px; + padding-left: 12px; + letter-spacing: 0.05em; } -.menu-item svg { - width: 18px; - height: 18px; +.secondary-nav-item { + display: flex; + align-items: center; + gap: 12px; + padding: 8px 12px; + border-radius: 6px; + cursor: pointer; + color: var(--text-primary); + font-size: 14px; + font-weight: 400; transition: var(--transition-smooth); } -.menu-item.active svg { - color: var(--sidebar-accent); - filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.3)); +.secondary-nav-item:hover { + background-color: #F8F8F8; +} + +.secondary-nav-item.active { + background-color: #F0F0F0; + font-weight: 500; } -.sidebar-footer { - display: none; +.nav-count-badge { + margin-left: auto; + font-size: 12px; + font-weight: 600; + color: var(--text-muted); +} + +.secondary-nav-item.active .nav-count-badge { + color: var(--text-primary); } /* Main Content Area */ diff --git a/src/App.jsx b/src/App.jsx index b3a64d5..82e364a 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,11 +1,12 @@ -import { useState, useMemo, lazy, Suspense } from 'react'; -import { Routes, Route, Navigate, useLocation } from 'react-router-dom'; +import { useState, useMemo, lazy, Suspense, useEffect } from 'react'; +import { Routes, Route, Navigate, useLocation, useNavigate } from 'react-router-dom'; import { LayoutDashboard, Briefcase, Users, Calendar, FileText, + GraduationCap, Bell, Settings, AlertTriangle, @@ -27,7 +28,16 @@ import { BarChart3, UserSearch, Video, - Download + Download, + ChevronsRight, + ChevronsLeft, + Mail, + MessageCircle, + Phone, + Inbox as InboxIcon, + File, + Trash2, + ChevronUp } from 'lucide-react'; import { ResponsiveContainer, @@ -42,7 +52,8 @@ import { Cell } from 'recharts'; import './App.css'; -import { loginWithGoogleAndCalendar } from './firebaseAuth'; +import { auth, loginWithGoogleAndCalendar } from './firebaseAuth'; +import { onAuthStateChanged } from 'firebase/auth'; import LandingPage from './LandingPage.jsx'; import Navbar from './Navbar.jsx'; import KnowledgeBase from './KnowledgeBase.jsx'; @@ -57,6 +68,10 @@ import MeetView from './MeetView.jsx'; import ExportView from './ExportView.jsx'; import EmailAutomationView from './EmailAutomationView.jsx'; import AnalysisView from './AnalysisView.jsx'; +import StudentTemplateBuilder from './pages/StudentTemplateBuilder.jsx'; +import EmployeeTemplateBuilder from './pages/EmployeeTemplateBuilder.jsx'; +import TeamTemplateBuilder from './pages/TeamTemplateBuilder.jsx'; +import ProtectedRoute from './components/ProtectedRoute.jsx'; const API_BASE_URL = import.meta.env.VITE_API_URL || "http://localhost:8000"; @@ -81,10 +96,109 @@ const avatars = [ export default function App() { const location = useLocation(); - const [showDashboard, setShowDashboard] = useState(false); - // --- STATE MANAGEMENT --- - const [activeTab, setActiveTab] = useState('Dashboard'); - const [searchQuery, setSearchQuery] = useState(''); + const navigate = useNavigate(); + + const PATH_TAB_MAP = { + '/dashboard': 'Dashboard', + '/dashboard/templates/student': 'Student Template', + '/dashboard/templates/employee': 'Employee Template', + '/dashboard/templates/team': 'Team Template', + '/dashboard/projects': 'Projects', + '/dashboard/teams': 'Teams', + '/dashboard/calendar': 'Calendar', + '/dashboard/reports': 'Reports', + '/dashboard/sourcing': 'Sourcing', + '/dashboard/meet': 'Meet', + '/dashboard/export': 'Export', + '/dashboard/email-automation': 'Email Automation', + '/dashboard/analysis': 'Analysis', + '/dashboard/alerts': 'Alerts', + '/dashboard/settings': 'Settings', + '/dashboard/knowledge-base': 'Knowledge Base', + }; + + const TAB_PATH_MAP = Object.fromEntries( + Object.entries(PATH_TAB_MAP).map(([path, tab]) => [tab, path]) + ); + + const activeTab = PATH_TAB_MAP[location.pathname] || 'Dashboard'; + + const calculatePrimaryNav = (tab) => { + if (['Dashboard', 'Alerts'].includes(tab)) return 'Home'; + if (['Student Template', 'Employee Template', 'Team Template'].includes(tab)) return 'Templates'; + if (['Projects', 'Teams', 'Sourcing', 'Calendar'].includes(tab)) return 'Workspace'; + if (['Analysis', 'Reports', 'Export'].includes(tab)) return 'Analytics'; + if (['Knowledge Base'].includes(tab)) return 'Intelligence'; + if (['Settings'].includes(tab)) return 'Settings'; + return 'Home'; + }; + + const activePrimaryNav = calculatePrimaryNav(activeTab); + const [isSidebarExpanded, setIsSidebarExpanded] = useState(true); + + const PRIMARY_NAVS = [ + { id: 'Home', icon: LayoutDashboard }, + { id: 'Inbox', icon: Mail }, + { id: 'Workspace', icon: Briefcase }, + { id: 'Templates', icon: FileText }, + { id: 'Analytics', icon: BarChart3 }, + { id: 'Intelligence', icon: Sparkles }, + { id: 'Settings', icon: Settings } + ]; + + const SECONDARY_NAVS = { + Home: [ + { id: 'Dashboard', label: 'Overview', icon: LayoutDashboard }, + { id: 'Alerts', label: 'Alerts', icon: AlertTriangle } + ], + Inbox: [ + { id: 'Assigned', label: 'Assigned to me', icon: Users, count: 50 }, + { id: 'Unassigned', label: 'Unassigned', icon: FileText, count: 2 }, + { id: 'AllOpen', label: 'All open', icon: CheckCircle2, count: 2 }, + { id: 'divider1', isDivider: true }, + { id: 'Email Automation', label: 'Email', icon: Mail, count: 46 }, + { id: 'Chat', label: 'Chat', icon: MessageCircle, count: 18 }, + { id: 'Calls', label: 'Calls', icon: Phone, count: 12 }, + { id: 'AllClosed', label: 'All Closed', icon: InboxIcon, count: 12 }, + { id: 'divider2', isDivider: true }, + { id: 'Sent', label: 'Sent', icon: Send, count: 12 }, + { id: 'Draft', label: 'Draft', icon: File }, + { id: 'Schedule', label: 'Schedule', icon: Clock }, + { id: 'divider3', isDivider: true }, + { id: 'OthersHeader', isHeader: true, label: 'Others' }, + { id: 'Spam', label: 'Spam', icon: AlertCircle }, + { id: 'Trash', label: 'Trash', icon: Trash2 }, + { id: 'divider4', isDivider: true }, + { id: 'TeamHeader', isHeader: true, label: 'Team inboxes' }, + { id: 'ManageSubscription', label: 'Manage Subscription', icon: Briefcase, count: 1 }, + { id: 'ManageLabels', label: 'Manage Labels', icon: Settings, count: 2 } + ], + Workspace: [ + { id: 'Projects', label: 'Projects', icon: Briefcase }, + { id: 'Teams', label: 'Teams', icon: Users }, + { id: 'Sourcing', label: 'Sourcing', icon: UserSearch }, + { id: 'Calendar', label: 'Calendar', icon: Calendar } + ], + Templates: [ + { id: 'Student Template', label: 'Student', icon: GraduationCap }, + { id: 'Employee Template', label: 'Employee', icon: Briefcase }, + { id: 'Team Template', label: 'Team', icon: Users } + ], + Analytics: [ + { id: 'Analysis', label: 'Analysis', icon: BarChart3 }, + { id: 'Reports', label: 'Reports', icon: FileText }, + { id: 'Export', label: 'Export', icon: Download } + ], + Intelligence: [ + { id: 'Knowledge Base', label: 'Knowledge Base', icon: Sparkles } + ], + Settings: [ + { id: 'Settings', label: 'General Settings', icon: Settings } + ] + }; + + const searchQueryState = useState(''); + const [searchQuery, setSearchQuery] = searchQueryState; const [datePreset, setDatePreset] = useState('This Month'); const [showDatePicker, setShowDatePicker] = useState(false); @@ -94,6 +208,7 @@ export default function App() { // Authentication & API state const [user, setUser] = useState(null); + const [authReady, setAuthReady] = useState(false); const [tokens, setTokens] = useState(null); const [loading, setLoading] = useState(false); const [apiError, setApiError] = useState(null); @@ -169,6 +284,44 @@ export default function App() { } ]); + // Auth persistence listener + useEffect(() => { + const unsubscribe = onAuthStateChanged(auth, async (currentUser) => { + if (currentUser) { + setUser(currentUser); + // Auto-redirect to dashboard if logging in from public landing pages + if (location.pathname === '/' || location.pathname === '/welcome' || location.pathname === '/security') { + navigate('/dashboard'); + } + + const googleToken = localStorage.getItem('googleAccessToken'); + try { + const firebaseToken = await currentUser.getIdToken(); + setTokens({ + firebaseIdToken: firebaseToken, + googleAccessToken: googleToken + }); + + if (googleToken) { + // Re-fetch events now that we have tokens + await fetchEvents(firebaseToken, googleToken); + } + } catch (e) { + console.error("Error restoring session:", e); + } + } else { + // Fallback for demo mode survival on refresh + const localUser = localStorage.getItem('authUser'); + if (localUser && localUser.includes("Demo Mode")) { + setUser(JSON.parse(localUser)); + } + } + // Mark auth as ready after first check completes + setAuthReady(true); + }); + return () => unsubscribe(); + }, []); + const [alerts, setAlerts] = useState([ { id: 1, @@ -205,6 +358,13 @@ export default function App() { firebaseIdToken: data.firebaseIdToken, googleAccessToken: data.googleAccessToken }); + // Store token in localStorage to survive refreshes + localStorage.setItem('googleAccessToken', data.googleAccessToken); + localStorage.setItem('authUser', JSON.stringify({ + displayName: data.user.displayName, + photoURL: data.user.photoURL, + email: data.user.email + })); await fetchEvents(data.firebaseIdToken, data.googleAccessToken); return true; } catch (err) { @@ -225,15 +385,17 @@ export default function App() { }; const enterDemoMode = () => { - setUser({ + const demoUser = { displayName: "Sarah Jenkins (Demo Mode)", photoURL: "https://images.unsplash.com/photo-1534528741775-53994a69daeb?auto=format&fit=crop&w=100&h=100&q=80", email: "demo@ledgerai.co" - }); + }; + setUser(demoUser); setTokens({ firebaseIdToken: "demo-firebase-id-token", googleAccessToken: "demo-google-access-token" }); + localStorage.setItem('authUser', JSON.stringify(demoUser)); // Reset to mock data setMeetings([ { @@ -304,16 +466,15 @@ export default function App() { } ]); setAuthErrorModal(null); - if (typeof setShowDashboard === 'function') { - setShowDashboard(true); - } }; const handleLogout = () => { + auth.signOut(); setUser(null); setTokens(null); setApiError(null); - setShowDashboard(false); + localStorage.removeItem('googleAccessToken'); + localStorage.removeItem('authUser'); // Reset to mock data setMeetings([ { @@ -680,216 +841,116 @@ export default function App() { // Navigation click handler const handleNavClick = (tab) => { - setActiveTab(tab); + const path = TAB_PATH_MAP[tab]; + if (path) navigate(path); }; - if (!showDashboard) { - const handleStartDashboard = async () => { - if (user) { - setShowDashboard(true); - } else { - const success = await handleLogin(); - if (success) { - setShowDashboard(true); - } + const handleStartDashboard = async () => { + if (user) { + navigate('/dashboard'); + } else { + const success = await handleLogin(); + if (success) { + navigate('/dashboard'); } - }; - - return ( - <> - {location.pathname !== '/welcome' && ( - - )} - -
- Loading LedgerAI Portal... -
- }> - - setApiError(null)} - /> - } /> - setApiError(null)} - /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - -
- - ); - } - - return ( -
- {/* --- SIDEBAR --- */} -