diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index 710ca71..0000000
--- a/.dockerignore
+++ /dev/null
@@ -1,27 +0,0 @@
-node_modules
-dist
-.git
-.github
-.gitignore
-.env
-.env.*
-!.env.example
-src_ref
-docs_ref
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-.DS_Store
-.idea
-.vscode
-coverage
-.turbo
-.next
-*.md
-!README.md
-backend-prompt.md
-MANUS_HANDOFF.md
-MODE_OPERATOIRE.md
-CLAUDE.md
diff --git a/.env.example b/.env.example
deleted file mode 100644
index 56156dd..0000000
--- a/.env.example
+++ /dev/null
@@ -1,61 +0,0 @@
-# ─── Database ───────────────────────────────────────────────────────────────
-# Local dev (host MySQL):
-# DATABASE_URL=mysql://queuemed:queuemed@localhost:3306/queuemed
-# Docker compose (uses the "db" service):
-# DATABASE_URL=mysql://queuemed:queuemed@db:3306/queuemed
-DATABASE_URL=mysql://queuemed:queuemed@localhost:3306/queuemed
-
-# ─── Auth ───────────────────────────────────────────────────────────────────
-# REQUIRED. Must be at least 32 characters of high-entropy random data.
-# Generate one with: openssl rand -hex 64
-# The server refuses to start if this is missing or too short.
-JWT_SECRET=replace_me_with_openssl_rand_hex_64_output
-
-# ─── Server ─────────────────────────────────────────────────────────────────
-PORT=5000
-NODE_ENV=development
-
-# Public URL used to build QR code links (e.g. https://queuemed.example.com).
-# In production this should match the public origin allowed by CORS.
-PUBLIC_BASE_URL=
-
-# ─── Stripe ─────────────────────────────────────────────────────────────────
-# All Stripe vars are OPTIONAL. If STRIPE_SECRET_KEY is not set, the app still
-# runs and the subscription UI shows a friendly "not configured" notice.
-STRIPE_SECRET_KEY=
-STRIPE_WEBHOOK_SECRET=
-STRIPE_BASIC_PRICE_ID=
-STRIPE_PRO_PRICE_ID=
-
-# Client-side price IDs — must be exposed at build time via VITE_ prefix.
-# Same values as STRIPE_BASIC_PRICE_ID / STRIPE_PRO_PRICE_ID.
-VITE_STRIPE_BASIC_PRICE_ID=
-VITE_STRIPE_PRO_PRICE_ID=
-
-# ─── WhatsApp (Baileys) ─────────────────────────────────────────────────────
-# Persistent directory used to store Baileys auth credentials per clinic.
-# Must live on a Docker volume in production so sessions survive restarts.
-WHATSAPP_SESSION_DIR=/app/data/whatsapp-sessions
-
-# ─── Twilio SMS ─────────────────────────────────────────────────────────────
-# All Twilio vars are OPTIONAL. If any is missing, SMS sending is disabled
-# and the app logs a warning instead of failing. Each clinic also has a
-# `smsEnabled` opt-in flag; SMS is never sent without both.
-TWILIO_ACCOUNT_SID=
-TWILIO_AUTH_TOKEN=
-TWILIO_PHONE_NUMBER=
-
-# ─── Docker compose only ────────────────────────────────────────────────────
-MYSQL_ROOT_PASSWORD=replace_me_with_a_strong_password
-MYSQL_DATABASE=queuemed
-MYSQL_USER=queuemed
-MYSQL_PASSWORD=replace_me_with_a_strong_password
-MYSQL_PORT=3306
-APP_PORT=5000
-
-# ─── Backups (used by scripts/backup-db.sh) ─────────────────────────────────
-# Inside the `app` container these point at the `db` service.
-# Override only if running the script outside docker compose.
-# MYSQL_HOST=db
-# BACKUP_DIR=/app/data/backups
-# BACKUP_KEEP=7
diff --git a/.gitignore b/.gitignore
index 4534cef..e69de29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,17 +0,0 @@
-node_modules/
-dist/
-.env
-.env.docker
-.env.local
-*.log
-.DS_Store
-Thumbs.db
-*.md
-!README.md
-!docs/
-.vscode/
-.idea/
-*.swp
-*.swo
-*~
-.claude/
diff --git a/AGENT_CONTEXT.md b/AGENT_CONTEXT.md
new file mode 100644
index 0000000..e69de29
diff --git a/AUTHORS.md b/AUTHORS.md
new file mode 100644
index 0000000..e69de29
diff --git a/CLAUDE.md b/CLAUDE.md
deleted file mode 100644
index 927a398..0000000
--- a/CLAUDE.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# QueueMed — Salle d'attente virtuelle pour cabinets médicaux
-
-## Architecture
-- **Frontend**: React 19, Vite 6, Tailwind CSS 4, shadcn/ui, wouter, Framer Motion, Recharts, Socket.io-client
-- **Backend**: Express 4, tRPC 11, Socket.io 4, Drizzle ORM
-- **Database**: MySQL 8
-- **Auth**: JWT + session cookie (simple email/password login, no OAuth)
-- **QR Code**: qrcode npm package with rotating anti-cheat tokens
-- **Deploy**: Docker + docker-compose, Nginx Proxy Manager for HTTPS
-
-## Theme — MEDICAL LIGHT
-- **Primary**: #10b981 (emerald-500) and #06b6d4 (cyan-500)
-- **Background**: white / #f0fdf4 (green-50) / #ecfeff (cyan-50)
-- **Cards**: white with subtle shadow, glass-morphism (backdrop-blur, bg-white/70)
-- **Accents**: #0d9488 (teal-600) for CTAs, #f97316 (orange-500) for alerts
-- **Feel**: clean, hygienic, medical — light green/cyan, translucent panels, rounded corners
-- **Font**: Inter (Google Fonts)
-
-## Database Schema (see docs_ref/schema.ts)
-5 tables: users, subscriptions, clinics, queueEntries, analyticsEvents
-
-## Key Routes
-| Route | Page | Access |
-|---|---|---|
-| / | Landing page (hero, features, pricing, testimonials) | Public |
-| /login | Login page | Public |
-| /dashboard | Doctor dashboard (KPIs, clinic list, quick actions) | Auth |
-| /dashboard/clinics | Manage clinics (CRUD, QR code, settings) | Auth |
-| /dashboard/queue/:clinicId | Real-time queue management | Auth |
-| /dashboard/analytics | Charts, CSV export, AI recommendations | Auth |
-| /dashboard/subscription | Subscription plans, trial, blocking | Auth |
-| /display/:clinicId | Display screen for tablet/monitor | Public |
-| /queue/:token | Patient interface (live position, alerts) | Public |
-| /ticket/:entryId | Printable ticket | Public |
-
-## Project Structure
-```
-/home/ubuntu/queue-med-deploy/
-├── client/
-│ ├── src/
-│ │ ├── main.tsx # React entry + wouter router
-│ │ ├── App.tsx # Layout shell
-│ │ ├── lib/
-│ │ │ └── trpc.ts # tRPC client setup
-│ │ ├── components/
-│ │ │ └── ui/ # shadcn/ui components
-│ │ ├── _core/
-│ │ │ └── hooks/
-│ │ │ └── useAuth.ts
-│ │ └── pages/
-│ │ ├── Home.tsx # Landing
-│ │ ├── Login.tsx
-│ │ ├── Dashboard.tsx
-│ │ ├── DoctorClinics.tsx
-│ │ ├── QueueManagement.tsx
-│ │ ├── Analytics.tsx
-│ │ ├── PatientQueue.tsx
-│ │ ├── DisplayScreen.tsx
-│ │ ├── SubscriptionPage.tsx
-│ │ ├── PrintTicket.tsx
-│ │ ├── Onboarding.tsx
-│ │ ├── Help.tsx
-│ │ └── QrPoster.tsx
-│ └── index.html
-├── server/
-│ ├── _core/
-│ │ ├── index.ts # Express + Socket.io server
-│ │ ├── trpc.ts # tRPC setup
-│ │ └── context.ts # Auth context
-│ ├── routers.ts # All tRPC procedures
-│ ├── db.ts # Drizzle helpers
-│ ├── schema.ts # Drizzle schema
-│ └── auth.ts # JWT auth logic
-├── shared/
-│ └── types.ts # Shared types
-├── drizzle.config.ts
-├── vite.config.ts
-├── tsconfig.json
-├── package.json
-├── Dockerfile
-├── docker-compose.yml
-└── .dockerignore
-```
-
-## Environment Variables
-- DATABASE_URL — MySQL connection string
-- JWT_SECRET — Secret for JWT signing
-- PORT — Server port (default 5000)
-- NODE_ENV — production/development
-
-## Socket.io Rooms
-- clinic:{clinicId} — Doctor + display screen
-- patient:{patientToken} — Individual patient
-- display:{clinicId} — Display screen only
-
-## Commands
-- pnpm dev — Start dev server
-- pnpm build — Production build
-- pnpm db:push — Push Drizzle migrations
-- pnpm start — Start production server
-
-## CRITICAL NOTES
-- Use existing pages in src_ref/ as reference for UI patterns and tRPC calls
-- The QR token rotation system is anti-cheat: tokens expire on schedule
-- Subscription middleware blocks sensitive procedures when expired
-- Socket.io is initialized in server/_core/index.ts and exposed globally
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 4372d95..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-# syntax=docker/dockerfile:1.7
-
-# ─── Stage 1 — install deps ─────────────────────────────────────────────────
-FROM node:22-alpine AS deps
-WORKDIR /app
-RUN apk add --no-cache git python3 make g++
-RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
-COPY package.json pnpm-lock.yaml* ./
-RUN pnpm install --frozen-lockfile || pnpm install
-
-# ─── Stage 2 — build client + server ─────────────────────────────────────────
-FROM node:22-alpine AS builder
-WORKDIR /app
-RUN apk add --no-cache git
-RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
-COPY --from=deps /app/node_modules ./node_modules
-COPY . .
-RUN pnpm build
-
-# ─── Stage 3 — runtime ──────────────────────────────────────────────────────
-FROM node:22-alpine AS runner
-WORKDIR /app
-ENV NODE_ENV=production \
- PORT=5000
-
-RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
-
-# Copy production deps + built assets
-COPY --from=deps /app/node_modules ./node_modules
-COPY --from=builder /app/dist ./dist
-COPY package.json tsconfig.json drizzle.config.ts ./
-COPY server ./server
-COPY shared ./shared
-
-# Persistent app data directory (WhatsApp sessions, DB backups, …).
-# In production this should be backed by a Docker named volume.
-RUN mkdir -p /app/data/whatsapp-sessions /app/data/backups
-
-# Bundle the operational scripts (DB backup, etc.)
-COPY scripts ./scripts
-RUN chmod +x ./scripts/*.sh || true
-
-# Tools used by the backup script
-RUN apk add --no-cache mysql-client
-
-RUN addgroup -S app && adduser -S app -G app && chown -R app:app /app
-USER app
-
-EXPOSE 5000
-
-HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
- CMD wget -qO- http://127.0.0.1:5000/api/health || exit 1
-
-CMD ["pnpm", "start"]
diff --git a/MODE_OPERATOIRE_QueueMed.pdf b/MODE_OPERATOIRE_QueueMed.pdf
new file mode 100644
index 0000000..d7021cf
Binary files /dev/null and b/MODE_OPERATOIRE_QueueMed.pdf differ
diff --git a/ROADMAP.html b/ROADMAP.html
new file mode 100644
index 0000000..e69de29
diff --git a/client/index.html b/client/index.html
deleted file mode 100644
index f9cfe11..0000000
--- a/client/index.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- QueueMed — Salle d'attente virtuelle
-
-
-
-
-
-
-
-
-
diff --git a/client/public/favicon.svg b/client/public/favicon.svg
deleted file mode 100644
index fce6a66..0000000
--- a/client/public/favicon.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/client/public/icon-192x192.svg b/client/public/icon-192x192.svg
deleted file mode 100644
index 9c82f55..0000000
--- a/client/public/icon-192x192.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/client/public/icon-512x512.svg b/client/public/icon-512x512.svg
deleted file mode 100644
index 7955f12..0000000
--- a/client/public/icon-512x512.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/client/src/App.tsx b/client/src/App.tsx
deleted file mode 100644
index 018b951..0000000
--- a/client/src/App.tsx
+++ /dev/null
@@ -1,140 +0,0 @@
-import { Route, Switch, Redirect } from "wouter";
-import { HelmetProvider } from "react-helmet-async";
-import { Toaster } from "@/components/ui/toast";
-import { useAuth } from "@/_core/hooks/useAuth";
-import Layout from "@/components/Layout";
-import { Loader2 } from "lucide-react";
-
-import Home from "@/pages/Home";
-import Login from "@/pages/Login";
-import ForgotPassword from "@/pages/ForgotPassword";
-import ResetPassword from "@/pages/ResetPassword";
-import Dashboard from "@/pages/Dashboard";
-import DoctorClinics from "@/pages/DoctorClinics";
-import QueueManagement from "@/pages/QueueManagement";
-import Analytics from "@/pages/Analytics";
-import PatientQueue from "@/pages/PatientQueue";
-import QrJoin from "@/pages/QrJoin";
-import DisplayScreen from "@/pages/DisplayScreen";
-import SubscriptionPage from "@/pages/SubscriptionPage";
-import PrintTicket from "@/pages/PrintTicket";
-import Onboarding from "@/pages/Onboarding";
-import Help from "@/pages/Help";
-import QrPoster from "@/pages/QrPoster";
-import ClinicSettings from "@/pages/ClinicSettings";
-import ConsultationHistory from "@/pages/ConsultationHistory";
-import WhatsAppSetup from "@/pages/WhatsAppSetup";
-import SubscriptionBlocked from "@/pages/SubscriptionBlocked";
-import SubscriptionSuccess from "@/pages/SubscriptionSuccess";
-import SubscriptionCancel from "@/pages/SubscriptionCancel";
-import AdminPanel from "@/pages/AdminPanel";
-import AdminSettings from "@/pages/AdminSettings";
-
-function ProtectedRoute({ children }: { children: React.ReactNode }) {
- const { isAuthenticated, loading } = useAuth();
-
- if (loading) {
- return (
-
-
-
- );
- }
- if (!isAuthenticated) return ;
- return {children} ;
-}
-
-export default function App() {
- return (
-
-
-
- {/* Public marketing & auth */}
-
-
-
-
-
-
- {/* Public patient/display routes */}
-
-
-
-
-
- {/* Authenticated routes (wrapped in Layout) */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Admin */}
-
-
-
-
-
-
-
- {/* Fallback */}
-
-
-
-
-
- );
-}
-
-function NotFound() {
- return (
-
- );
-}
diff --git a/client/src/_core/hooks/useAuth.ts b/client/src/_core/hooks/useAuth.ts
deleted file mode 100644
index 8811715..0000000
--- a/client/src/_core/hooks/useAuth.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { useCallback } from "react";
-import { useLocation } from "wouter";
-import { useQueryClient } from "@tanstack/react-query";
-import { toast } from "sonner";
-import { trpc } from "@/lib/trpc";
-
-export function useAuth() {
- const [, navigate] = useLocation();
- const queryClient = useQueryClient();
-
- const meQuery = trpc.auth.me.useQuery(undefined, {
- retry: false,
- staleTime: 60_000,
- });
-
- const loginMutation = trpc.auth.login.useMutation({
- onSuccess: async () => {
- await meQuery.refetch();
- await queryClient.invalidateQueries();
- toast.success("Connecté avec succès");
- },
- onError: (e) => toast.error(e.message),
- });
-
- const registerMutation = trpc.auth.register.useMutation({
- onSuccess: async () => {
- await meQuery.refetch();
- await queryClient.invalidateQueries();
- toast.success("Compte créé — bienvenue sur QueueMed !");
- },
- onError: (e) => toast.error(e.message),
- });
-
- const logoutMutation = trpc.auth.logout.useMutation({
- onSuccess: async () => {
- await queryClient.clear();
- await meQuery.refetch();
- navigate("/");
- toast.success("Déconnecté");
- },
- });
-
- const login = useCallback(
- (email: string, password: string) => loginMutation.mutateAsync({ email, password }),
- [loginMutation]
- );
-
- const register = useCallback(
- (email: string, password: string, name?: string) =>
- registerMutation.mutateAsync({ email, password, name }),
- [registerMutation]
- );
-
- const logout = useCallback(() => logoutMutation.mutate(), [logoutMutation]);
-
- return {
- user: meQuery.data ?? null,
- isAuthenticated: !!meQuery.data,
- loading: meQuery.isLoading,
- login,
- register,
- logout,
- isLoggingIn: loginMutation.isPending,
- isRegistering: registerMutation.isPending,
- };
-}
diff --git a/client/src/components/CountryCodeManager.tsx b/client/src/components/CountryCodeManager.tsx
deleted file mode 100644
index 2d5f805..0000000
--- a/client/src/components/CountryCodeManager.tsx
+++ /dev/null
@@ -1,291 +0,0 @@
-import { useState, useMemo } from "react";
-import { trpc } from "@/lib/trpc";
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Badge } from "@/components/ui/badge";
-import { toast } from "sonner";
-import {
- Globe,
- Search,
- CheckCircle,
- Circle,
- Loader2,
- ChevronDown,
- ChevronUp,
- ToggleLeft,
- ToggleRight,
-} from "lucide-react";
-
-type CountryCode = {
- id: number;
- code: string;
- dialCode: string;
- nameFr: string;
- flag: string;
- enabled: boolean;
- sortOrder: number;
-};
-
-// Groupes régionaux pour organiser l'affichage
-const REGION_GROUPS: { label: string; codes: string[] }[] = [
- {
- label: "France & DOM-TOM",
- codes: ["FR", "GP", "MQ", "RE", "GF", "PM", "YT", "NC", "PF", "WF"],
- },
- {
- label: "Europe",
- codes: ["BE", "CH", "LU", "MC", "DE", "ES", "IT", "PT", "GB", "NL", "PL", "SE", "NO", "DK", "FI", "AT", "GR", "RO", "HU", "CZ", "TR"],
- },
- {
- label: "Afrique francophone",
- codes: ["MA", "DZ", "TN", "SN", "CI", "CM", "CD", "CG", "MG", "ML", "BF", "NE", "TD", "GN", "BJ", "TG", "MR", "GA", "GQ", "CF", "KM", "DJ", "MU", "SC", "EG"],
- },
- {
- label: "Amériques",
- codes: ["US", "CA", "MX", "BR", "AR", "CO", "CL", "PE", "VE", "EC", "BO", "PY", "UY", "HT"],
- },
- {
- label: "Asie & Océanie",
- codes: ["IN", "CN", "JP", "AU", "LB"],
- },
-];
-
-export default function CountryCodeManager() {
- const utils = trpc.useUtils();
- const [search, setSearch] = useState("");
- const [expandedGroups, setExpandedGroups] = useState>(new Set(["France & DOM-TOM"]));
- const [pendingToggles, setPendingToggles] = useState>(new Set());
-
- const { data: allCodes = [], isLoading } = trpc.whatsapp.listAllCountryCodes.useQuery();
-
- const toggleMut = trpc.whatsapp.toggleCountryCode.useMutation({
- onMutate: ({ code }) => {
- setPendingToggles((prev) => new Set(prev).add(code));
- },
- onSuccess: (data) => {
- setPendingToggles((prev) => {
- const next = new Set(prev);
- next.delete(data.code);
- return next;
- });
- utils.whatsapp.listAllCountryCodes.invalidate();
- utils.whatsapp.listCountryCodes.invalidate();
- toast.success(data.enabled ? "Indicatif activé" : "Indicatif désactivé");
- },
- onError: (err, { code }) => {
- setPendingToggles((prev) => {
- const next = new Set(prev);
- next.delete(code);
- return next;
- });
- toast.error(err.message);
- },
- });
-
- const bulkMut = trpc.whatsapp.bulkToggleCountryCodes.useMutation({
- onSuccess: (data, vars) => {
- utils.whatsapp.listAllCountryCodes.invalidate();
- utils.whatsapp.listCountryCodes.invalidate();
- toast.success(`${data.count} indicatifs ${vars.enabled ? "activés" : "désactivés"}`);
- },
- onError: (err) => toast.error(err.message),
- });
-
- // Map code → entry for quick lookup
- const codeMap = useMemo(() => {
- const m = new Map();
- allCodes.forEach((c) => m.set(c.code, c));
- return m;
- }, [allCodes]);
-
- // Filtered list for search mode
- const searchResults = useMemo(() => {
- if (!search.trim()) return [];
- const q = search.toLowerCase();
- return allCodes.filter(
- (c) =>
- c.nameFr.toLowerCase().includes(q) ||
- c.code.toLowerCase().includes(q) ||
- c.dialCode.includes(q)
- );
- }, [allCodes, search]);
-
- const toggleGroup = (label: string) => {
- setExpandedGroups((prev) => {
- const next = new Set(prev);
- if (next.has(label)) next.delete(label);
- else next.add(label);
- return next;
- });
- };
-
- const handleToggle = (code: string, currentEnabled: boolean) => {
- toggleMut.mutate({ code, enabled: !currentEnabled });
- };
-
- const handleBulkGroup = (codes: string[], enabled: boolean) => {
- const validCodes = codes.filter((c) => codeMap.has(c));
- bulkMut.mutate({ codes: validCodes, enabled });
- };
-
- const enabledCount = allCodes.filter((c) => c.enabled).length;
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- const renderCountryRow = (c: CountryCode) => {
- const isPending = pendingToggles.has(c.code);
- return (
-
-
-
{c.flag}
-
- {c.nameFr}
- +{c.dialCode} · {c.code}
-
-
-
handleToggle(c.code, c.enabled)}
- disabled={isPending}
- className={`shrink-0 ml-3 transition-colors ${
- c.enabled ? "text-emerald-400 hover:text-emerald-300" : "text-muted-foreground hover:text-foreground"
- }`}
- title={c.enabled ? "Désactiver" : "Activer"}
- >
- {isPending ? (
-
- ) : c.enabled ? (
-
- ) : (
-
- )}
-
-
- );
- };
-
- return (
-
-
-
-
-
-
- Indicatifs pays disponibles
-
-
- Choisissez les pays affichés aux patients dans le formulaire WhatsApp.{" "}
-
- {enabledCount} activé{enabledCount > 1 ? "s" : ""}
-
-
-
-
-
- {/* Search */}
-
-
- setSearch(e.target.value)}
- className="pl-9 bg-background/50"
- />
-
-
-
-
- {/* Search results */}
- {search.trim() ? (
-
- {searchResults.length === 0 ? (
-
Aucun résultat pour « {search} »
- ) : (
- searchResults.map((c) => renderCountryRow(c))
- )}
-
- ) : (
- /* Grouped view */
- REGION_GROUPS.map((group) => {
- const groupCodes = group.codes
- .map((code) => codeMap.get(code))
- .filter(Boolean) as CountryCode[];
- if (groupCodes.length === 0) return null;
-
- const isExpanded = expandedGroups.has(group.label);
- const groupEnabled = groupCodes.filter((c) => c.enabled).length;
-
- return (
-
- {/* Group header */}
-
toggleGroup(group.label)}
- >
-
- {group.label}
-
- {groupEnabled}/{groupCodes.length}
-
-
-
- {/* Bulk actions */}
- {
- e.stopPropagation();
- handleBulkGroup(group.codes, true);
- }}
- disabled={bulkMut.isPending}
- >
-
- Tout activer
-
- {
- e.stopPropagation();
- handleBulkGroup(group.codes, false);
- }}
- disabled={bulkMut.isPending}
- >
-
- Tout désactiver
-
- {isExpanded ? (
-
- ) : (
-
- )}
-
-
-
- {/* Group rows */}
- {isExpanded && (
-
- {groupCodes.map((c) => renderCountryRow(c))}
-
- )}
-
- );
- })
- )}
-
-
- );
-}
diff --git a/client/src/components/Layout.tsx b/client/src/components/Layout.tsx
deleted file mode 100644
index 6042801..0000000
--- a/client/src/components/Layout.tsx
+++ /dev/null
@@ -1,210 +0,0 @@
-import { useState } from "react";
-import { Link, useLocation } from "wouter";
-import { useTranslation } from "react-i18next";
-import {
- LayoutDashboard, Building2, BarChart3, CreditCard,
- HelpCircle, LogOut, Stethoscope, Menu, X, Shield, Settings,
-} from "lucide-react";
-import { useAuth } from "@/_core/hooks/useAuth";
-import { cn } from "@/lib/utils";
-
-function LanguageSwitcher({ className = "" }: { className?: string }) {
- const { i18n } = useTranslation();
- const current = i18n.resolvedLanguage ?? i18n.language ?? "fr";
- const change = (lng: "fr" | "en") => i18n.changeLanguage(lng);
- return (
-
- change("fr")}
- className={cn(
- "px-2.5 py-1 transition-colors",
- current.startsWith("fr") ? "bg-emerald-500 text-white" : "text-slate-600 hover:bg-emerald-50"
- )}
- aria-pressed={current.startsWith("fr")}
- >
- FR
-
- change("en")}
- className={cn(
- "px-2.5 py-1 transition-colors",
- current.startsWith("en") ? "bg-emerald-500 text-white" : "text-slate-600 hover:bg-emerald-50"
- )}
- aria-pressed={current.startsWith("en")}
- >
- EN
-
-
- );
-}
-
-export default function Layout({ children }: { children: React.ReactNode }) {
- const { t } = useTranslation();
- const [location] = useLocation();
- const { user, logout } = useAuth();
- const [mobileOpen, setMobileOpen] = useState(false);
-
- const NAV = [
- { href: "/dashboard", label: t("nav.dashboard"), icon: LayoutDashboard },
- { href: "/dashboard/clinics", label: t("nav.clinics"), icon: Building2 },
- { href: "/dashboard/analytics", label: t("nav.analytics"), icon: BarChart3 },
- { href: "/dashboard/subscription", label: t("nav.subscription"), icon: CreditCard },
- { href: "/help", label: t("nav.help"), icon: HelpCircle },
- ...(user?.role === "admin"
- ? [{ href: "/admin", label: "Admin", icon: Shield }, { href: "/admin/settings", label: "Param\u00e8tres", icon: Settings }]
- : []),
- ];
-
- const isActive = (href: string) =>
- href === "/dashboard"
- ? location === "/dashboard"
- : location === href || location.startsWith(href + "/");
-
- return (
-
- {/* ─── Sidebar (desktop) ──────────────────────────────────────────── */}
-
-
- {/* ─── Main column ───────────────────────────────────────────────── */}
-
- {/* Top bar (mobile) */}
-
-
- {/* Mobile drawer */}
- {mobileOpen && (
-
-
setMobileOpen(false)}
- />
-
-
- )}
-
-
{children}
-
-
- );
-}
diff --git a/client/src/components/PhoneDialCodePicker.tsx b/client/src/components/PhoneDialCodePicker.tsx
deleted file mode 100644
index f5a8a94..0000000
--- a/client/src/components/PhoneDialCodePicker.tsx
+++ /dev/null
@@ -1,242 +0,0 @@
-/**
- * PhoneDialCodePicker
- * Sélecteur d'indicatif pays + champ numéro local pour les notifications WhatsApp.
- * - Affiche uniquement les pays activés par l'admin (trpc.whatsapp.listCountryCodes)
- * - Valide la longueur et le format du numéro selon les règles par pays
- * - Expose onValidationChange pour que le parent puisse bloquer la soumission
- */
-import { useState, useRef, useEffect, useMemo } from "react";
-import { trpc } from "@/lib/trpc";
-import { Loader2, ChevronDown, Search, AlertCircle, CheckCircle2 } from "lucide-react";
-import {
- validateLocalPhone,
- getPhonePlaceholder,
- getPhoneHint,
-} from "@shared/phoneValidation";
-
-type CountryCode = {
- id: number;
- code: string;
- dialCode: string;
- nameFr: string;
- flag: string;
- enabled: boolean;
- sortOrder: number;
-};
-
-type Props = {
- /** Numéro complet au format international sans + (ex: "33612345678") */
- value: string;
- onChange: (fullNumber: string) => void;
- /** Appelé avec null si valide, message d'erreur sinon */
- onValidationChange?: (error: string | null) => void;
- className?: string;
-};
-
-export default function PhoneDialCodePicker({
- value,
- onChange,
- onValidationChange,
- className = "",
-}: Props) {
- const { data: countries = [], isLoading } = trpc.whatsapp.listCountryCodes.useQuery();
-
- const [selectedCode, setSelectedCode] = useState
(null);
- const [localNumber, setLocalNumber] = useState("");
- const [touched, setTouched] = useState(false);
- const [dropdownOpen, setDropdownOpen] = useState(false);
- const [search, setSearch] = useState("");
- const dropdownRef = useRef(null);
-
- // Auto-select first country once loaded
- useEffect(() => {
- if (countries.length > 0 && !selectedCode) {
- setSelectedCode(countries[0]);
- }
- }, [countries, selectedCode]);
-
- // Sync outgoing value + validation
- useEffect(() => {
- if (!selectedCode) return;
- const cleaned = localNumber.replace(/\D/g, "").replace(/^0+/, "");
- const full = cleaned ? `${selectedCode.dialCode}${cleaned}` : "";
- onChange(full);
-
- if (onValidationChange) {
- if (!cleaned) {
- // Empty = not yet filled, no error shown until touched
- onValidationChange(touched ? "Veuillez saisir votre numéro." : null);
- } else {
- const err = validateLocalPhone(selectedCode.dialCode, cleaned);
- onValidationChange(err);
- }
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [selectedCode, localNumber, touched]);
-
- // Close dropdown on outside click
- useEffect(() => {
- const handler = (e: MouseEvent) => {
- if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
- setDropdownOpen(false);
- setSearch("");
- }
- };
- document.addEventListener("mousedown", handler);
- return () => document.removeEventListener("mousedown", handler);
- }, []);
-
- const filtered = useMemo(() => {
- if (!search.trim()) return countries;
- const q = search.toLowerCase();
- return countries.filter(
- (c) =>
- c.nameFr.toLowerCase().includes(q) ||
- c.code.toLowerCase().includes(q) ||
- c.dialCode.includes(q)
- );
- }, [countries, search]);
-
- // Compute validation state for display
- const cleaned = localNumber.replace(/\D/g, "").replace(/^0+/, "");
- const validationError = selectedCode && cleaned
- ? validateLocalPhone(selectedCode.dialCode, cleaned)
- : null;
- const isValid = cleaned.length > 0 && validationError === null;
- const showError = touched && cleaned.length > 0 && validationError !== null;
-
- const placeholder = selectedCode ? getPhonePlaceholder(selectedCode.dialCode) : "123456789";
- const hint = selectedCode ? getPhoneHint(selectedCode.dialCode) : "";
-
- if (isLoading) {
- return (
-
-
- Chargement…
-
- );
- }
-
- if (countries.length === 0) {
- return (
- setLocalNumber(e.target.value)}
- placeholder="Numéro international (ex: 33612345678)"
- className={`w-full bg-background/50 border border-emerald-500/40 rounded-xl px-4 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-emerald-500/70 ${className}`}
- />
- );
- }
-
- return (
-
-
- {/* Dial code selector */}
-
setDropdownOpen((o) => !o)}
- className={`flex items-center gap-1.5 px-3 py-2.5 bg-background/50 border rounded-xl text-sm text-foreground hover:border-emerald-500/70 transition-colors shrink-0 min-w-[96px] ${
- showError ? "border-red-500/60" : "border-emerald-500/40"
- }`}
- >
- {selectedCode ? (
- <>
- {selectedCode.flag}
- +{selectedCode.dialCode}
- >
- ) : (
- Pays
- )}
-
-
-
- {/* Local number input */}
-
-
setLocalNumber(e.target.value)}
- onBlur={() => setTouched(true)}
- placeholder={placeholder}
- className={`w-full bg-background/50 border rounded-xl px-4 py-2.5 pr-9 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none transition-colors ${
- showError
- ? "border-red-500/60 focus:border-red-500/80"
- : isValid
- ? "border-emerald-500/60 focus:border-emerald-500/80"
- : "border-emerald-500/40 focus:border-emerald-500/70"
- }`}
- />
- {/* Validation icon */}
- {cleaned.length > 0 && (
-
- {isValid ? (
-
- ) : (
-
- )}
-
- )}
-
-
- {/* Dropdown */}
- {dropdownOpen && (
-
- {/* Search */}
-
-
-
- setSearch(e.target.value)}
- placeholder="Rechercher…"
- className="w-full pl-8 pr-3 py-1.5 text-sm bg-background/50 border border-border/50 rounded-lg text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary/60"
- />
-
-
-
- {/* Country list */}
-
- {filtered.length === 0 ? (
-
Aucun résultat
- ) : (
- filtered.map((c) => (
-
{
- setSelectedCode(c);
- setDropdownOpen(false);
- setSearch("");
- setTouched(false); // reset validation on country change
- setLocalNumber(""); // reset number on country change
- }}
- className={`w-full flex items-center gap-3 px-3 py-2.5 text-left hover:bg-accent transition-colors ${
- selectedCode?.code === c.code ? "bg-emerald-500/10" : ""
- }`}
- >
- {c.flag}
- {c.nameFr}
- +{c.dialCode}
-
- ))
- )}
-
-
- )}
-
-
- {/* Validation message or hint */}
- {showError ? (
-
-
- {validationError}
-
- ) : (
-
{hint}
- )}
-
- );
-}
diff --git a/client/src/components/PractitionerManager.tsx b/client/src/components/PractitionerManager.tsx
deleted file mode 100644
index f9bf950..0000000
--- a/client/src/components/PractitionerManager.tsx
+++ /dev/null
@@ -1,233 +0,0 @@
-import { useState } from "react";
-import { Loader2, Plus, Trash2, UserPlus, Users } from "lucide-react";
-import { trpc } from "@/lib/trpc";
-import { Button } from "@/components/ui/button";
-import { toast } from "sonner";
-
-const PRESET_COLORS = [
- "#10b981", // emerald
- "#06b6d4", // cyan
- "#0d9488", // teal
- "#8b5cf6", // violet
- "#f97316", // orange
- "#ec4899", // pink
- "#3b82f6", // blue
- "#eab308", // yellow
-];
-
-export default function PractitionerManager({ clinicId }: { clinicId: number }) {
- const utils = trpc.useUtils();
- const membersQuery = trpc.clinic.listMembers.useQuery(
- { clinicId },
- { enabled: clinicId > 0 }
- );
-
- const [adding, setAdding] = useState(false);
- const [email, setEmail] = useState("");
- const [displayName, setDisplayName] = useState("");
- const [color, setColor] = useState(PRESET_COLORS[0]);
-
- const addMember = trpc.clinic.addMember.useMutation({
- onSuccess: () => {
- toast.success("Praticien ajouté");
- utils.clinic.listMembers.invalidate({ clinicId });
- utils.clinic.listMembersPublic.invalidate({ clinicId });
- setEmail("");
- setDisplayName("");
- setColor(PRESET_COLORS[0]);
- setAdding(false);
- },
- onError: (e) => toast.error(e.message),
- });
-
- const removeMember = trpc.clinic.removeMember.useMutation({
- onSuccess: () => {
- toast.success("Praticien retiré");
- utils.clinic.listMembers.invalidate({ clinicId });
- utils.clinic.listMembersPublic.invalidate({ clinicId });
- },
- onError: (e) => toast.error(e.message),
- });
-
- const updateMember = trpc.clinic.updateMember.useMutation({
- onSuccess: () => {
- utils.clinic.listMembers.invalidate({ clinicId });
- utils.clinic.listMembersPublic.invalidate({ clinicId });
- },
- onError: (e) => toast.error(e.message),
- });
-
- const handleAdd = () => {
- if (!email.trim()) {
- toast.error("Email requis");
- return;
- }
- addMember.mutate({
- clinicId,
- email: email.trim(),
- displayName: displayName.trim() || undefined,
- color,
- });
- };
-
- const members = membersQuery.data ?? [];
-
- return (
-
-
-
-
-
-
-
-
Praticiens du cabinet
-
- Multi-médecins · couleur d'identification
-
-
-
-
setAdding((v) => !v)}
- >
- {adding ? (
- "Annuler"
- ) : (
- <>
- Ajouter
- >
- )}
-
-
-
- {adding && (
-
-
-
- Email du praticien
-
-
setEmail(e.target.value)}
- placeholder="docteur@example.com"
- className="w-full px-3 py-2 rounded-lg border border-slate-200 bg-white text-sm focus:outline-none focus:border-emerald-400"
- />
-
- Le praticien doit déjà avoir un compte QueueMed.
-
-
-
-
- Nom affiché (optionnel)
-
- setDisplayName(e.target.value)}
- placeholder="Dr. Martin"
- className="w-full px-3 py-2 rounded-lg border border-slate-200 bg-white text-sm focus:outline-none focus:border-emerald-400"
- />
-
-
-
- Couleur d'identification
-
-
- {PRESET_COLORS.map((c) => (
- setColor(c)}
- className={`w-8 h-8 rounded-lg border-2 transition-all ${
- color === c
- ? "border-slate-900 scale-110 shadow-md"
- : "border-white"
- }`}
- style={{ background: c }}
- aria-label={`Couleur ${c}`}
- />
- ))}
- setColor(e.target.value)}
- className="w-8 h-8 rounded-lg cursor-pointer"
- aria-label="Couleur personnalisée"
- />
-
-
-
- {addMember.isPending ? (
-
- ) : (
-
- )}
- Ajouter le praticien
-
-
- )}
-
- {membersQuery.isLoading ? (
-
-
-
- ) : members.length === 0 ? (
-
- Aucun praticien associé. Ajoutez-en un pour activer l'attribution.
-
- ) : (
-
- {members.map((m) => (
-
-
- updateMember.mutate({
- clinicId,
- memberId: m.id,
- color: e.target.value,
- })
- }
- className="w-9 h-9 rounded-lg border border-slate-200 cursor-pointer flex-shrink-0"
- aria-label="Modifier la couleur"
- />
-
-
- {m.displayName ?? m.name ?? m.email ?? "—"}
-
-
- {m.email ?? "—"} · {m.role}
-
-
-
- removeMember.mutate({ clinicId, memberId: m.id })
- }
- disabled={removeMember.isPending || m.role === "owner"}
- className="w-8 h-8 rounded-lg flex items-center justify-center text-red-600 hover:bg-red-50 disabled:opacity-30"
- title={
- m.role === "owner"
- ? "Le propriétaire ne peut être retiré"
- : "Retirer ce praticien"
- }
- >
-
-
-
- ))}
-
- )}
-
- );
-}
diff --git a/client/src/components/WhatsAppTemplateEditor.tsx b/client/src/components/WhatsAppTemplateEditor.tsx
deleted file mode 100644
index 63920bd..0000000
--- a/client/src/components/WhatsAppTemplateEditor.tsx
+++ /dev/null
@@ -1,352 +0,0 @@
-import { useState, useRef, useCallback, useMemo, useEffect } from "react";
-import { trpc } from "@/lib/trpc";
-import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
-import { Textarea } from "@/components/ui/textarea";
-import { Badge } from "@/components/ui/badge";
-import { toast } from "sonner";
-import {
- DEFAULT_TEMPLATES,
- TEMPLATE_VARIABLES,
- TEMPLATE_LABELS,
- SAMPLE_CONTEXT,
- interpolateTemplate,
- type TemplateType,
-} from "../../../shared/whatsappTemplates";
-import { Save, RotateCcw, Eye, EyeOff, MessageSquare, Sparkles } from "lucide-react";
-
-interface WhatsAppTemplateEditorProps {
- clinicId: number;
-}
-
-export default function WhatsAppTemplateEditor({ clinicId }: WhatsAppTemplateEditorProps) {
- const { data: templates, isLoading, refetch } = trpc.clinicSettings.getTemplates.useQuery({ clinicId });
- const updateMutation = trpc.clinicSettings.updateTemplates.useMutation({
- onSuccess: () => {
- toast.success("Templates sauvegardés", { description: "Les modèles de messages ont été mis à jour." });
- refetch();
- },
- onError: (err) => {
- toast.error("Erreur", { description: err.message });
- },
- });
-
- const templateTypes: TemplateType[] = ["joined", "soon", "called", "withdrawn"];
-
- // Local state for each template
- const [localTemplates, setLocalTemplates] = useState>({
- joined: "",
- soon: "",
- called: "",
- withdrawn: "",
- });
-
- // Track which templates have been modified
- const [modified, setModified] = useState>({
- joined: false,
- soon: false,
- called: false,
- withdrawn: false,
- });
-
- // Preview toggle per template
- const [showPreview, setShowPreview] = useState>({
- joined: false,
- soon: false,
- called: false,
- withdrawn: false,
- });
-
- // Active tab
- const [activeTab, setActiveTab] = useState("joined");
-
- // Refs for textareas
- const textareaRefs = useRef>({
- joined: null,
- soon: null,
- called: null,
- withdrawn: null,
- });
-
- // Initialize local state from server data
- useEffect(() => {
- if (templates) {
- setLocalTemplates({
- joined: templates.joined ?? DEFAULT_TEMPLATES.joined,
- soon: templates.soon ?? DEFAULT_TEMPLATES.soon,
- called: templates.called ?? DEFAULT_TEMPLATES.called,
- withdrawn: templates.withdrawn ?? DEFAULT_TEMPLATES.withdrawn,
- });
- setModified({ joined: false, soon: false, called: false, withdrawn: false });
- }
- }, [templates]);
-
- const handleChange = useCallback((type: TemplateType, value: string) => {
- setLocalTemplates((prev) => ({ ...prev, [type]: value }));
- setModified((prev) => ({ ...prev, [type]: true }));
- }, []);
-
- const insertVariable = useCallback((type: TemplateType, variable: string) => {
- const textarea = textareaRefs.current[type];
- if (textarea) {
- const start = textarea.selectionStart;
- const end = textarea.selectionEnd;
- const current = localTemplates[type];
- const newValue = current.substring(0, start) + variable + current.substring(end);
- setLocalTemplates((prev) => ({ ...prev, [type]: newValue }));
- setModified((prev) => ({ ...prev, [type]: true }));
- // Restore cursor position after variable
- setTimeout(() => {
- textarea.focus();
- textarea.selectionStart = start + variable.length;
- textarea.selectionEnd = start + variable.length;
- }, 0);
- } else {
- // Fallback: append at end
- setLocalTemplates((prev) => ({ ...prev, [type]: prev[type] + variable }));
- setModified((prev) => ({ ...prev, [type]: true }));
- }
- }, [localTemplates]);
-
- const resetToDefault = useCallback((type: TemplateType) => {
- setLocalTemplates((prev) => ({ ...prev, [type]: DEFAULT_TEMPLATES[type] }));
- setModified((prev) => ({ ...prev, [type]: true }));
- }, []);
-
- const togglePreview = useCallback((type: TemplateType) => {
- setShowPreview((prev) => ({ ...prev, [type]: !prev[type] }));
- }, []);
-
- const handleSave = useCallback(() => {
- const payload: Record = { clinicId: clinicId as any };
- for (const type of templateTypes) {
- if (modified[type]) {
- // If it's the same as default, save null (use default)
- if (localTemplates[type] === DEFAULT_TEMPLATES[type]) {
- (payload as any)[type] = null;
- } else {
- (payload as any)[type] = localTemplates[type];
- }
- }
- }
- updateMutation.mutate(payload as any);
- setModified({ joined: false, soon: false, called: false, withdrawn: false });
- }, [localTemplates, modified, clinicId, updateMutation]);
-
- const hasAnyModification = Object.values(modified).some(Boolean);
-
- // Preview rendering with highlighted variables
- const renderPreview = useCallback((template: string) => {
- const rendered = interpolateTemplate(template, SAMPLE_CONTEXT);
- return rendered;
- }, []);
-
- // Highlight variables in template text
- const highlightVariables = useCallback((text: string) => {
- const parts = text.split(/(\{\{[a-z]+\}\})/g);
- return parts.map((part, i) => {
- if (part.match(/^\{\{[a-z]+\}\}$/)) {
- return (
-
- {part}
-
- );
- }
- return {part} ;
- });
- }, []);
-
- if (isLoading) {
- return (
-
-
-
-
-
- );
- }
-
- const activeLabel = TEMPLATE_LABELS[activeTab];
-
- return (
-
-
-
-
-
-
- Modèles de messages WhatsApp
-
-
- Personnalisez les messages envoyés automatiquement aux patients. Cliquez sur une variable pour l'insérer.
-
-
- {hasAnyModification && (
-
-
- {updateMutation.isPending ? "Sauvegarde..." : "Sauvegarder"}
-
- )}
-
-
-
- {/* Variables reference */}
-
-
-
- Variables disponibles
-
-
- {TEMPLATE_VARIABLES.map((v) => (
- insertVariable(activeTab, v.key)}
- className="group relative inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md bg-background/80 border border-border/50 hover:border-teal-500/50 hover:bg-teal-500/10 transition-all cursor-pointer"
- title={v.description}
- >
- {v.key}
- {v.label}
-
- ))}
-
-
-
- {/* Template tabs */}
-
- {templateTypes.map((type) => {
- const label = TEMPLATE_LABELS[type];
- return (
- setActiveTab(type)}
- className={`flex-1 flex items-center justify-center gap-1.5 px-3 py-2 rounded-md text-sm font-medium transition-all ${
- activeTab === type
- ? "bg-background text-foreground shadow-sm"
- : "text-muted-foreground hover:text-foreground hover:bg-background/50"
- }`}
- >
- {label.icon}
- {label.title}
- {modified[type] && (
-
- )}
-
- );
- })}
-
-
- {/* Active template editor */}
-
-
-
-
{activeLabel.icon} {activeLabel.title}
-
{activeLabel.description}
-
-
- togglePreview(activeTab)}
- className="text-xs"
- >
- {showPreview[activeTab] ? (
- <> Éditer>
- ) : (
- <> Aperçu>
- )}
-
- resetToDefault(activeTab)}
- className="text-xs"
- >
- Par défaut
-
-
-
-
- {showPreview[activeTab] ? (
- /* Preview mode – WhatsApp-style bubble */
-
-
-
- {renderPreview(localTemplates[activeTab])}
-
-
- Aperçu avec données fictives
-
-
-
- ) : (
- /* Edit mode */
-
- )}
-
-
- {/* Quick preview of all templates */}
-
-
Aperçu rapide de tous les messages
-
- {templateTypes.map((type) => {
- const label = TEMPLATE_LABELS[type];
- const isCustom = templates && templates[type] !== null;
- return (
-
setActiveTab(type)}
- className={`p-3 rounded-lg border cursor-pointer transition-all ${
- activeTab === type
- ? "border-teal-500/50 bg-teal-500/5"
- : "border-border/30 bg-background/30 hover:border-border/60"
- }`}
- >
-
-
- {label.icon} {label.title}
-
- {isCustom ? (
-
- Personnalisé
-
- ) : (
-
- Par défaut
-
- )}
-
-
- {localTemplates[type].substring(0, 80)}...
-
-
- );
- })}
-
-
-
-
- );
-}
diff --git a/client/src/components/ui/accordion.tsx b/client/src/components/ui/accordion.tsx
deleted file mode 100644
index 62705e3..0000000
--- a/client/src/components/ui/accordion.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import * as React from "react";
-import * as AccordionPrimitive from "@radix-ui/react-accordion";
-import { ChevronDownIcon } from "lucide-react";
-
-import { cn } from "@/lib/utils";
-
-function Accordion({
- ...props
-}: React.ComponentProps) {
- return ;
-}
-
-function AccordionItem({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AccordionTrigger({
- className,
- children,
- ...props
-}: React.ComponentProps) {
- return (
-
- svg]:rotate-180",
- className
- )}
- {...props}
- >
- {children}
-
-
-
- );
-}
-
-function AccordionContent({
- className,
- children,
- ...props
-}: React.ComponentProps) {
- return (
-
- {children}
-
- );
-}
-
-export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
diff --git a/client/src/components/ui/alert-dialog.tsx b/client/src/components/ui/alert-dialog.tsx
deleted file mode 100644
index 6949979..0000000
--- a/client/src/components/ui/alert-dialog.tsx
+++ /dev/null
@@ -1,155 +0,0 @@
-import * as React from "react";
-import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
-
-import { cn } from "@/lib/utils";
-import { buttonVariants } from "@/components/ui/button";
-
-function AlertDialog({
- ...props
-}: React.ComponentProps) {
- return ;
-}
-
-function AlertDialogTrigger({
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AlertDialogPortal({
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AlertDialogOverlay({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AlertDialogContent({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
-
-
-
- );
-}
-
-function AlertDialogHeader({
- className,
- ...props
-}: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function AlertDialogFooter({
- className,
- ...props
-}: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function AlertDialogTitle({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AlertDialogDescription({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AlertDialogAction({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AlertDialogCancel({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-export {
- AlertDialog,
- AlertDialogPortal,
- AlertDialogOverlay,
- AlertDialogTrigger,
- AlertDialogContent,
- AlertDialogHeader,
- AlertDialogFooter,
- AlertDialogTitle,
- AlertDialogDescription,
- AlertDialogAction,
- AlertDialogCancel,
-};
diff --git a/client/src/components/ui/alert.tsx b/client/src/components/ui/alert.tsx
deleted file mode 100644
index 5b1a0b5..0000000
--- a/client/src/components/ui/alert.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import * as React from "react";
-import { cva, type VariantProps } from "class-variance-authority";
-
-import { cn } from "@/lib/utils";
-
-const alertVariants = cva(
- "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
- {
- variants: {
- variant: {
- default: "bg-card text-card-foreground",
- destructive:
- "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-);
-
-function Alert({
- className,
- variant,
- ...props
-}: React.ComponentProps<"div"> & VariantProps) {
- return (
-
- );
-}
-
-function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function AlertDescription({
- className,
- ...props
-}: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-export { Alert, AlertTitle, AlertDescription };
diff --git a/client/src/components/ui/aspect-ratio.tsx b/client/src/components/ui/aspect-ratio.tsx
deleted file mode 100644
index 01d045d..0000000
--- a/client/src/components/ui/aspect-ratio.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio";
-
-function AspectRatio({
- ...props
-}: React.ComponentProps) {
- return ;
-}
-
-export { AspectRatio };
diff --git a/client/src/components/ui/avatar.tsx b/client/src/components/ui/avatar.tsx
deleted file mode 100644
index 02305fd..0000000
--- a/client/src/components/ui/avatar.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import * as React from "react";
-import * as AvatarPrimitive from "@radix-ui/react-avatar";
-
-import { cn } from "@/lib/utils";
-
-function Avatar({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AvatarImage({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-function AvatarFallback({
- className,
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-export { Avatar, AvatarImage, AvatarFallback };
diff --git a/client/src/components/ui/badge.tsx b/client/src/components/ui/badge.tsx
deleted file mode 100644
index 83750ed..0000000
--- a/client/src/components/ui/badge.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import * as React from "react";
-import { Slot } from "@radix-ui/react-slot";
-import { cva, type VariantProps } from "class-variance-authority";
-
-import { cn } from "@/lib/utils";
-
-const badgeVariants = cva(
- "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
- {
- variants: {
- variant: {
- default:
- "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
- secondary:
- "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
- destructive:
- "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
- outline:
- "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-);
-
-function Badge({
- className,
- variant,
- asChild = false,
- ...props
-}: React.ComponentProps<"span"> &
- VariantProps & { asChild?: boolean }) {
- const Comp = asChild ? Slot : "span";
-
- return (
-
- );
-}
-
-export { Badge, badgeVariants };
diff --git a/client/src/components/ui/breadcrumb.tsx b/client/src/components/ui/breadcrumb.tsx
deleted file mode 100644
index 9d88a37..0000000
--- a/client/src/components/ui/breadcrumb.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import * as React from "react";
-import { Slot } from "@radix-ui/react-slot";
-import { ChevronRight, MoreHorizontal } from "lucide-react";
-
-import { cn } from "@/lib/utils";
-
-function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
- return ;
-}
-
-function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
- return (
-
- );
-}
-
-function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
- return (
-
- );
-}
-
-function BreadcrumbLink({
- asChild,
- className,
- ...props
-}: React.ComponentProps<"a"> & {
- asChild?: boolean;
-}) {
- const Comp = asChild ? Slot : "a";
-
- return (
-
- );
-}
-
-function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
- return (
-
- );
-}
-
-function BreadcrumbSeparator({
- children,
- className,
- ...props
-}: React.ComponentProps<"li">) {
- return (
- svg]:size-3.5", className)}
- {...props}
- >
- {children ?? }
-
- );
-}
-
-function BreadcrumbEllipsis({
- className,
- ...props
-}: React.ComponentProps<"span">) {
- return (
-
-
- More
-
- );
-}
-
-export {
- Breadcrumb,
- BreadcrumbList,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbPage,
- BreadcrumbSeparator,
- BreadcrumbEllipsis,
-};
diff --git a/client/src/components/ui/button-group.tsx b/client/src/components/ui/button-group.tsx
deleted file mode 100644
index 30139ec..0000000
--- a/client/src/components/ui/button-group.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import { Slot } from "@radix-ui/react-slot";
-import { cva, type VariantProps } from "class-variance-authority";
-
-import { cn } from "@/lib/utils";
-import { Separator } from "@/components/ui/separator";
-
-const buttonGroupVariants = cva(
- "flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
- {
- variants: {
- orientation: {
- horizontal:
- "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
- vertical:
- "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
- },
- },
- defaultVariants: {
- orientation: "horizontal",
- },
- }
-);
-
-function ButtonGroup({
- className,
- orientation,
- ...props
-}: React.ComponentProps<"div"> & VariantProps) {
- return (
-
- );
-}
-
-function ButtonGroupText({
- className,
- asChild = false,
- ...props
-}: React.ComponentProps<"div"> & {
- asChild?: boolean;
-}) {
- const Comp = asChild ? Slot : "div";
-
- return (
-
- );
-}
-
-function ButtonGroupSeparator({
- className,
- orientation = "vertical",
- ...props
-}: React.ComponentProps) {
- return (
-
- );
-}
-
-export {
- ButtonGroup,
- ButtonGroupSeparator,
- ButtonGroupText,
- buttonGroupVariants,
-};
diff --git a/client/src/components/ui/button.tsx b/client/src/components/ui/button.tsx
deleted file mode 100644
index aff3448..0000000
--- a/client/src/components/ui/button.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import * as React from "react";
-import { Slot } from "@radix-ui/react-slot";
-import { cva, type VariantProps } from "class-variance-authority";
-
-import { cn } from "@/lib/utils";
-
-const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
- {
- variants: {
- variant: {
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
- destructive:
- "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
- outline:
- "border bg-transparent shadow-xs hover:bg-accent dark:bg-transparent dark:border-input dark:hover:bg-input/50",
- secondary:
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
- ghost:
- "hover:bg-accent dark:hover:bg-accent/50",
- link: "text-primary underline-offset-4 hover:underline",
- gradient:
- "bg-gradient-to-r from-emerald-500 to-cyan-500 text-white shadow-md hover:shadow-lg hover:from-emerald-600 hover:to-cyan-600",
- },
- size: {
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
- xl: "h-12 rounded-xl px-8 text-base has-[>svg]:px-6",
- icon: "size-9",
- "icon-sm": "size-8",
- "icon-lg": "size-10",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- }
-);
-
-function Button({
- className,
- variant,
- size,
- asChild = false,
- ...props
-}: React.ComponentProps<"button"> &
- VariantProps & {
- asChild?: boolean;
- }) {
- const Comp = asChild ? Slot : "button";
-
- return (
-
- );
-}
-
-export { Button, buttonVariants };
diff --git a/client/src/components/ui/calendar.tsx b/client/src/components/ui/calendar.tsx
deleted file mode 100644
index 48d4543..0000000
--- a/client/src/components/ui/calendar.tsx
+++ /dev/null
@@ -1,211 +0,0 @@
-import * as React from "react";
-import {
- ChevronDownIcon,
- ChevronLeftIcon,
- ChevronRightIcon,
-} from "lucide-react";
-import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker";
-
-import { cn } from "@/lib/utils";
-import { Button, buttonVariants } from "@/components/ui/button";
-
-function Calendar({
- className,
- classNames,
- showOutsideDays = true,
- captionLayout = "label",
- buttonVariant = "ghost",
- formatters,
- components,
- ...props
-}: React.ComponentProps & {
- buttonVariant?: React.ComponentProps["variant"];
-}) {
- const defaultClassNames = getDefaultClassNames();
-
- return (
- svg]:rotate-180`,
- String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
- className
- )}
- captionLayout={captionLayout}
- formatters={{
- formatMonthDropdown: date =>
- date.toLocaleString("default", { month: "short" }),
- ...formatters,
- }}
- classNames={{
- root: cn("w-fit", defaultClassNames.root),
- months: cn(
- "flex gap-4 flex-col md:flex-row relative",
- defaultClassNames.months
- ),
- month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
- nav: cn(
- "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
- defaultClassNames.nav
- ),
- button_previous: cn(
- buttonVariants({ variant: buttonVariant }),
- "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
- defaultClassNames.button_previous
- ),
- button_next: cn(
- buttonVariants({ variant: buttonVariant }),
- "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
- defaultClassNames.button_next
- ),
- month_caption: cn(
- "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
- defaultClassNames.month_caption
- ),
- dropdowns: cn(
- "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
- defaultClassNames.dropdowns
- ),
- dropdown_root: cn(
- "relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
- defaultClassNames.dropdown_root
- ),
- dropdown: cn(
- "absolute bg-popover inset-0 opacity-0",
- defaultClassNames.dropdown
- ),
- caption_label: cn(
- "select-none font-medium",
- captionLayout === "label"
- ? "text-sm"
- : "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
- defaultClassNames.caption_label
- ),
- table: "w-full border-collapse",
- weekdays: cn("flex", defaultClassNames.weekdays),
- weekday: cn(
- "text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
- defaultClassNames.weekday
- ),
- week: cn("flex w-full mt-2", defaultClassNames.week),
- week_number_header: cn(
- "select-none w-(--cell-size)",
- defaultClassNames.week_number_header
- ),
- week_number: cn(
- "text-[0.8rem] select-none text-muted-foreground",
- defaultClassNames.week_number
- ),
- day: cn(
- "relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
- defaultClassNames.day
- ),
- range_start: cn(
- "rounded-l-md bg-accent",
- defaultClassNames.range_start
- ),
- range_middle: cn("rounded-none", defaultClassNames.range_middle),
- range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
- today: cn(
- "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
- defaultClassNames.today
- ),
- outside: cn(
- "text-muted-foreground aria-selected:text-muted-foreground",
- defaultClassNames.outside
- ),
- disabled: cn(
- "text-muted-foreground opacity-50",
- defaultClassNames.disabled
- ),
- hidden: cn("invisible", defaultClassNames.hidden),
- ...classNames,
- }}
- components={{
- Root: ({ className, rootRef, ...props }) => {
- return (
-
- );
- },
- Chevron: ({ className, orientation, ...props }) => {
- if (orientation === "left") {
- return (
-
- );
- }
-
- if (orientation === "right") {
- return (
-
- );
- }
-
- return (
-
- );
- },
- DayButton: CalendarDayButton,
- WeekNumber: ({ children, ...props }) => {
- return (
-
-
- {children}
-
-
- );
- },
- ...components,
- }}
- {...props}
- />
- );
-}
-
-function CalendarDayButton({
- className,
- day,
- modifiers,
- ...props
-}: React.ComponentProps) {
- const defaultClassNames = getDefaultClassNames();
-
- const ref = React.useRef(null);
- React.useEffect(() => {
- if (modifiers.focused) ref.current?.focus();
- }, [modifiers.focused]);
-
- return (
- span]:text-xs [&>span]:opacity-70",
- defaultClassNames.day,
- className
- )}
- {...props}
- />
- );
-}
-
-export { Calendar, CalendarDayButton };
diff --git a/client/src/components/ui/card.tsx b/client/src/components/ui/card.tsx
deleted file mode 100644
index e8c0939..0000000
--- a/client/src/components/ui/card.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-function Card({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function CardAction({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function CardContent({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- );
-}
-
-export {
- Card,
- CardHeader,
- CardFooter,
- CardTitle,
- CardAction,
- CardDescription,
- CardContent,
-};
diff --git a/client/src/components/ui/carousel.tsx b/client/src/components/ui/carousel.tsx
deleted file mode 100644
index 03a9617..0000000
--- a/client/src/components/ui/carousel.tsx
+++ /dev/null
@@ -1,239 +0,0 @@
-import * as React from "react";
-import useEmblaCarousel, {
- type UseEmblaCarouselType,
-} from "embla-carousel-react";
-import { ArrowLeft, ArrowRight } from "lucide-react";
-
-import { cn } from "@/lib/utils";
-import { Button } from "@/components/ui/button";
-
-type CarouselApi = UseEmblaCarouselType[1];
-type UseCarouselParameters = Parameters;
-type CarouselOptions = UseCarouselParameters[0];
-type CarouselPlugin = UseCarouselParameters[1];
-
-type CarouselProps = {
- opts?: CarouselOptions;
- plugins?: CarouselPlugin;
- orientation?: "horizontal" | "vertical";
- setApi?: (api: CarouselApi) => void;
-};
-
-type CarouselContextProps = {
- carouselRef: ReturnType[0];
- api: ReturnType[1];
- scrollPrev: () => void;
- scrollNext: () => void;
- canScrollPrev: boolean;
- canScrollNext: boolean;
-} & CarouselProps;
-
-const CarouselContext = React.createContext(null);
-
-function useCarousel() {
- const context = React.useContext(CarouselContext);
-
- if (!context) {
- throw new Error("useCarousel must be used within a ");
- }
-
- return context;
-}
-
-function Carousel({
- orientation = "horizontal",
- opts,
- setApi,
- plugins,
- className,
- children,
- ...props
-}: React.ComponentProps<"div"> & CarouselProps) {
- const [carouselRef, api] = useEmblaCarousel(
- {
- ...opts,
- axis: orientation === "horizontal" ? "x" : "y",
- },
- plugins
- );
- const [canScrollPrev, setCanScrollPrev] = React.useState(false);
- const [canScrollNext, setCanScrollNext] = React.useState(false);
-
- const onSelect = React.useCallback((api: CarouselApi) => {
- if (!api) return;
- setCanScrollPrev(api.canScrollPrev());
- setCanScrollNext(api.canScrollNext());
- }, []);
-
- const scrollPrev = React.useCallback(() => {
- api?.scrollPrev();
- }, [api]);
-
- const scrollNext = React.useCallback(() => {
- api?.scrollNext();
- }, [api]);
-
- const handleKeyDown = React.useCallback(
- (event: React.KeyboardEvent) => {
- if (event.key === "ArrowLeft") {
- event.preventDefault();
- scrollPrev();
- } else if (event.key === "ArrowRight") {
- event.preventDefault();
- scrollNext();
- }
- },
- [scrollPrev, scrollNext]
- );
-
- React.useEffect(() => {
- if (!api || !setApi) return;
- setApi(api);
- }, [api, setApi]);
-
- React.useEffect(() => {
- if (!api) return;
- onSelect(api);
- api.on("reInit", onSelect);
- api.on("select", onSelect);
-
- return () => {
- api?.off("select", onSelect);
- };
- }, [api, onSelect]);
-
- return (
-
-
- {children}
-
-
- );
-}
-
-function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
- const { carouselRef, orientation } = useCarousel();
-
- return (
-
- );
-}
-
-function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
- const { orientation } = useCarousel();
-
- return (
-
- );
-}
-
-function CarouselPrevious({
- className,
- variant = "outline",
- size = "icon",
- ...props
-}: React.ComponentProps) {
- const { orientation, scrollPrev, canScrollPrev } = useCarousel();
-
- return (
-
-
- Previous slide
-
- );
-}
-
-function CarouselNext({
- className,
- variant = "outline",
- size = "icon",
- ...props
-}: React.ComponentProps) {
- const { orientation, scrollNext, canScrollNext } = useCarousel();
-
- return (
-
-
- Next slide
-
- );
-}
-
-export {
- type CarouselApi,
- Carousel,
- CarouselContent,
- CarouselItem,
- CarouselPrevious,
- CarouselNext,
-};
diff --git a/client/src/components/ui/chart.tsx b/client/src/components/ui/chart.tsx
deleted file mode 100644
index f93f6c4..0000000
--- a/client/src/components/ui/chart.tsx
+++ /dev/null
@@ -1,355 +0,0 @@
-import * as React from "react";
-import * as RechartsPrimitive from "recharts";
-
-import { cn } from "@/lib/utils";
-
-// Format: { THEME_NAME: CSS_SELECTOR }
-const THEMES = { light: "", dark: ".dark" } as const;
-
-export type ChartConfig = {
- [k in string]: {
- label?: React.ReactNode;
- icon?: React.ComponentType;
- } & (
- | { color?: string; theme?: never }
- | { color?: never; theme: Record }
- );
-};
-
-type ChartContextProps = {
- config: ChartConfig;
-};
-
-const ChartContext = React.createContext(null);
-
-function useChart() {
- const context = React.useContext(ChartContext);
-
- if (!context) {
- throw new Error("useChart must be used within a ");
- }
-
- return context;
-}
-
-function ChartContainer({
- id,
- className,
- children,
- config,
- ...props
-}: React.ComponentProps<"div"> & {
- config: ChartConfig;
- children: React.ComponentProps<
- typeof RechartsPrimitive.ResponsiveContainer
- >["children"];
-}) {
- const uniqueId = React.useId();
- const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
-
- return (
-
-
-
-
- {children}
-
-
-
- );
-}
-
-const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
- const colorConfig = Object.entries(config).filter(
- ([, config]) => config.theme || config.color
- );
-
- if (!colorConfig.length) {
- return null;
- }
-
- return (
-
-
- );
-}
diff --git a/client/src/pages/QrJoin.tsx b/client/src/pages/QrJoin.tsx
deleted file mode 100644
index 6a90186..0000000
--- a/client/src/pages/QrJoin.tsx
+++ /dev/null
@@ -1,194 +0,0 @@
-import { useState } from "react";
-import { useParams, useLocation } from "wouter";
-import { Helmet } from "react-helmet-async";
-import { useTranslation } from "react-i18next";
-import { motion } from "framer-motion";
-import {
- Stethoscope, QrCode, Smartphone, Loader2, XCircle, User, Phone, MessageCircle,
-} from "lucide-react";
-import { trpc } from "@/lib/trpc";
-import { Button } from "@/components/ui/button";
-import { toast } from "sonner";
-
-const VISIT_REASONS = [
- "consultation", "urgence", "certificat_scolaire", "certificat_sportif",
- "arret_travail", "administratif", "autre",
-] as const;
-
-export default function QrJoin() {
- const { t } = useTranslation();
- const params = useParams<{ clinicId: string; qrToken: string }>();
- const [, navigate] = useLocation();
- const clinicId = parseInt(params.clinicId ?? "0", 10);
- const qrToken = params.qrToken ?? "";
-
- const [name, setName] = useState("");
- const [phone, setPhone] = useState("");
- const [whatsappPhone, setWhatsappPhone] = useState("");
- const [reason, setReason] = useState("consultation");
- const [useSamePhone, setUseSamePhone] = useState(true);
-
- // Verify QR is valid first
- const verifyQuery = trpc.queue.verifyQr.useQuery(
- { clinicId, qrToken },
- { enabled: !!qrToken && clinicId > 0, retry: false }
- );
-
- const joinMutation = trpc.queue.join.useMutation({
- onSuccess: (data) => {
- toast.success(t("patient.toastJoined"));
- navigate(`/queue/${data.patientToken}`);
- },
- onError: (e) => {
- toast.error(e.message);
- },
- });
-
- if (verifyQuery.isLoading) {
- return (
-
- QueueMed
-
-
- );
- }
-
- if (verifyQuery.error || !verifyQuery.data) {
- return (
-
-
QueueMed
-
-
-
{t("patient.ticketNotFound")}
-
- {t("patient.ticketNotFoundDesc")}
-
-
navigate("/")}>{t("common.backToHome")}
-
-
- );
- }
-
- const { clinicName, isQueueOpen, whatsappConnected } = verifyQuery.data;
-
- if (!isQueueOpen) {
- return (
-
-
QueueMed — {clinicName}
-
-
-
File d'attente fermée
-
- Le cabinet {clinicName} n'accepte plus de patients pour le moment.
-
-
navigate("/")}>{t("common.backToHome")}
-
-
- );
- }
-
- const handleSubmit = (e: React.FormEvent) => {
- e.preventDefault();
- joinMutation.mutate({
- clinicId,
- qrToken,
- patientName: name || undefined,
- patientPhone: phone || undefined,
- whatsappPhone: useSamePhone ? phone : whatsappPhone || undefined,
- visitReason: reason as any,
- });
- };
-
- return (
-
-
QueueMed — {clinicName}
-
-
-
-
-
-
{clinicName}
-
Rejoignez la salle d'attente virtuelle
-
-
-
-
-
- );
-}
diff --git a/client/src/pages/QrPoster.tsx b/client/src/pages/QrPoster.tsx
deleted file mode 100644
index 2fc4e62..0000000
--- a/client/src/pages/QrPoster.tsx
+++ /dev/null
@@ -1,316 +0,0 @@
-import { useParams, useLocation } from "wouter";
-import { Helmet } from "react-helmet-async";
-import { useTranslation } from "react-i18next";
-import {
- Stethoscope, Printer, ChevronLeft, Loader2, QrCode,
- RefreshCw, MapPin, Phone, Smartphone, Hand, Bell,
-} from "lucide-react";
-import { trpc } from "@/lib/trpc";
-import { Button } from "@/components/ui/button";
-
-export default function QrPoster() {
- const { t } = useTranslation();
- const params = useParams<{ clinicId: string }>();
- const [, navigate] = useLocation();
- const clinicId = parseInt(params.clinicId ?? "0", 10);
-
- const baseUrl = typeof window !== "undefined" ? window.location.origin : "";
-
- const clinicQuery = trpc.clinic.getById.useQuery(
- { id: clinicId },
- { enabled: clinicId > 0 }
- );
- const qrQuery = trpc.clinic.qrDataUrl.useQuery(
- { id: clinicId, baseUrl },
- { enabled: clinicId > 0 }
- );
-
- const clinic = clinicQuery.data;
- const qrDataUrl = qrQuery.data?.dataUrl;
- const qrUrl = qrQuery.data?.url;
-
- if (clinicQuery.isLoading || qrQuery.isLoading) {
- return (
-
-
- {t("qrPoster.metaTitle")}
-
-
-
- );
- }
-
- if (clinicQuery.error || !clinic) {
- return (
-
-
- {t("qrPoster.metaTitle")}
-
-
-
{t("qrPoster.notFoundTitle")}
-
- {t("qrPoster.notFoundBody")}
-
-
navigate("/dashboard/clinics")}>
- {t("qrPoster.backToClinics")}
-
-
-
- );
- }
-
- const steps = [
- {
- Icon: Smartphone,
- num: "1",
- title: t("qrPoster.steps.scan.title"),
- desc: t("qrPoster.steps.scan.desc"),
- },
- {
- Icon: Hand,
- num: "2",
- title: t("qrPoster.steps.join.title"),
- desc: t("qrPoster.steps.join.desc"),
- },
- {
- Icon: Bell,
- num: "3",
- title: t("qrPoster.steps.wait.title"),
- desc: t("qrPoster.steps.wait.desc"),
- },
- ];
-
- return (
-
-
- {t("qrPoster.metaTitle")}
-
-
- {/* Controls — hidden on print */}
-
-
-
navigate(`/dashboard/queue/${clinicId}`)}
- className="flex items-center gap-2 text-slate-500 hover:text-emerald-700 transition-colors text-sm"
- >
-
- {t("qrPoster.backToManagement")}
-
-
-
qrQuery.refetch()}
- disabled={qrQuery.isFetching}
- size="sm"
- >
-
- {t("qrPoster.refresh")}
-
-
window.print()}
- className="font-semibold"
- >
-
- {t("qrPoster.printPoster")}
-
-
-
-
-
-
-
- {t("qrPoster.tipsTitle")} {" "}
- {t("qrPoster.tipsBody")}
-
-
-
-
- {/* Printable poster */}
-
-
- {/* Header band */}
-
-
-
- {t("qrPoster.tagline")}
-
-
-
- {/* Main content */}
-
-
- {clinic.name}
-
- {clinic.address && (
-
-
- {clinic.address}
-
- )}
- {clinic.phone && (
-
-
- {clinic.phone}
-
- )}
-
-
-
- {t("qrPoster.scanToJoin")}
-
-
- {t("qrPoster.followInRealTime")}
-
-
-
- {/* QR Code */}
-
-
- {qrDataUrl ? (
-
- ) : (
-
- {t("qrPoster.qrUnavailable")}
-
- )}
-
-
-
- {/* Steps */}
-
- {steps.map((step) => (
-
-
-
- {step.title}
-
-
- {step.desc}
-
-
- ))}
-
-
- {/* Info box */}
-
-
- ✓
-
-
-
- {t("qrPoster.noAppTitle")}
-
-
- {t("qrPoster.noAppBody")}
-
-
-
-
-
- {t("qrPoster.noSmartphoneNote")}
-
-
- {qrUrl && (
-
- {qrUrl}
-
- )}
-
-
- {/* Footer */}
-
- {t("qrPoster.poweredBy")}
- queuemed.fr
-
-
-
-
-
-
- );
-}
diff --git a/client/src/pages/QueueManagement.tsx b/client/src/pages/QueueManagement.tsx
deleted file mode 100644
index 5c3d772..0000000
--- a/client/src/pages/QueueManagement.tsx
+++ /dev/null
@@ -1,511 +0,0 @@
-import { useEffect, useState } from "react";
-import { useParams, useLocation } from "wouter";
-import { Helmet } from "react-helmet-async";
-import { useTranslation } from "react-i18next";
-import {
- ChevronLeft, Play, UserX, CheckCircle2, Trash2, Monitor, Users, Clock,
- Printer, RefreshCw, Loader2, Power, PowerOff, QrCode, Sparkles, Stethoscope,
-} from "lucide-react";
-import { trpc } from "@/lib/trpc";
-import { Button } from "@/components/ui/button";
-import { getSocket } from "@/lib/socket";
-import { toast } from "sonner";
-import { formatTicket, formatTime } from "@/lib/utils";
-import type { QueueEntryStatus } from "@shared/types";
-
-export default function QueueManagement() {
- const { t } = useTranslation();
- const params = useParams<{ clinicId: string }>();
- const [, navigate] = useLocation();
- const clinicId = Number(params.clinicId ?? 0);
- const utils = trpc.useUtils();
-
- const queueQuery = trpc.queue.getForDoctor.useQuery(
- { clinicId },
- { enabled: !!clinicId, refetchInterval: 15_000 }
- );
-
- const membersQuery = trpc.clinic.listMembers.useQuery(
- { clinicId },
- { enabled: !!clinicId }
- );
-
- const baseUrl = typeof window !== "undefined" ? window.location.origin : undefined;
- const qrQuery = trpc.clinic.qrDataUrl.useQuery(
- { id: clinicId, baseUrl },
- { enabled: !!clinicId, refetchInterval: 60_000 }
- );
-
- // ─── Socket ──────────────────────────────────────────
- useEffect(() => {
- if (!clinicId) return;
- const s = getSocket();
- s.emit("clinic:subscribe", clinicId);
- const onUpdate = () => utils.queue.getForDoctor.invalidate({ clinicId });
- const onQr = () => utils.clinic.qrDataUrl.invalidate({ id: clinicId, baseUrl });
- s.on("queue:update", onUpdate);
- s.on("qr:rotated", onQr);
- return () => {
- s.emit("clinic:unsubscribe", clinicId);
- s.off("queue:update", onUpdate);
- s.off("qr:rotated", onQr);
- };
- }, [clinicId, utils, baseUrl]);
-
- // ─── Mutations ───────────────────────────────────────
- const callNext = trpc.queue.callNext.useMutation({
- onSuccess: (d) => {
- if (d.called) toast.success(t("queue.toastTicketCalled", { number: formatTicket(d.called.ticketNumber) }));
- else toast(t("queue.noPatients"));
- utils.queue.getForDoctor.invalidate({ clinicId });
- },
- onError: (e) => toast.error(e.message),
- });
-
- const markAbsent = trpc.queue.markAbsent.useMutation({
- onSuccess: () => { toast.success(t("queue.toastPatientAbsent")); utils.queue.getForDoctor.invalidate({ clinicId }); },
- onError: (e) => toast.error(e.message),
- });
-
- const markDone = trpc.queue.markDone.useMutation({
- onSuccess: () => { toast.success(t("queue.toastConsultDone")); utils.queue.getForDoctor.invalidate({ clinicId }); },
- onError: (e) => toast.error(e.message),
- });
-
- const callSpecific = trpc.queue.callSpecific.useMutation({
- onSuccess: () => { toast.success(t("queue.toastPatientCalled")); utils.queue.getForDoctor.invalidate({ clinicId }); },
- onError: (e) => toast.error(e.message),
- });
-
- const reset = trpc.queue.reset.useMutation({
- onSuccess: () => { toast.success(t("queue.toastQueueReset")); utils.queue.getForDoctor.invalidate({ clinicId }); },
- onError: (e) => toast.error(e.message),
- });
-
- const printTicket = trpc.queue.joinPrinted.useMutation({
- onSuccess: (d) => {
- toast.success(t("queue.toastTicketCreated", { number: formatTicket(d.ticketNumber) }));
- window.open(`/ticket/${d.entryId}`, "_blank");
- utils.queue.getForDoctor.invalidate({ clinicId });
- },
- onError: (e) => toast.error(e.message),
- });
-
- const toggleQueue = trpc.clinic.update.useMutation({
- onSuccess: () => { utils.queue.getForDoctor.invalidate({ clinicId }); utils.clinic.list.invalidate(); },
- onError: (e) => toast.error(e.message),
- });
-
- const reorder = trpc.queue.reorder.useMutation({
- onSuccess: () => utils.queue.getForDoctor.invalidate({ clinicId }),
- onError: (e) => { toast.error(e.message); utils.queue.getForDoctor.invalidate({ clinicId }); },
- });
-
- const regenQr = trpc.clinic.regenerateQr.useMutation({
- onSuccess: () => { toast.success(t("queue.toastQrRegenerated")); utils.clinic.qrDataUrl.invalidate({ id: clinicId, baseUrl }); },
- onError: (e) => toast.error(e.message),
- });
-
- // ─── Derived ─────────────────────────────────────────
- const data = queueQuery.data;
- const clinic = data?.clinic;
- const allQueue = data?.queue ?? [];
- const members = membersQuery.data ?? [];
- const memberById = new Map(members.map((m) => [m.id, m]));
-
- const [practitionerFilter, setPractitionerFilter] = useState(null);
- const [practitionerForCall, setPractitionerForCall] = useState(null);
-
- const queue = practitionerFilter
- ? allQueue.filter((e) => e.practitionerId === practitionerFilter)
- : allQueue;
- const waiting = queue.filter((e) => e.status === "waiting");
- const called = queue.filter((e) => e.status === "called" || e.status === "in_consultation");
-
- const [confirmReset, setConfirmReset] = useState(false);
-
- // ─── Drag & drop reordering ──────────────────────────
- const [dragId, setDragId] = useState(null);
- const [dragOverId, setDragOverId] = useState(null);
-
- const handleDrop = (target: number) => {
- if (dragId === null || dragId === target) {
- setDragId(null);
- setDragOverId(null);
- return;
- }
- const ids = waiting.map((e) => e.id);
- const fromIdx = ids.indexOf(dragId);
- const toIdx = ids.indexOf(target);
- if (fromIdx < 0 || toIdx < 0) return;
- const reordered = [...ids];
- const [moved] = reordered.splice(fromIdx, 1);
- reordered.splice(toIdx, 0, moved);
- reorder.mutate({ clinicId, orderedEntryIds: reordered });
- setDragId(null);
- setDragOverId(null);
- };
-
- if (!clinicId) {
- return (
-
-
- {t("queue.metaTitle")}
-
-
-
{t("queue.clinicNotFound")}
-
- );
- }
-
- return (
-
-
- {t("queue.metaTitle")}
-
-
- {/* ─── Header ───────────────────────────────────────── */}
-
-
navigate("/dashboard")}>
- {t("common.back")}
-
-
-
{clinic?.name ?? t("common.loading")}
-
- {t("queue.headerCounts", { waiting: waiting.length, called: called.length })}
-
-
-
-
window.open(`/display/${clinicId}`, "_blank")}
- title={t("queue.displayScreen")}
- >
-
-
-
toggleQueue.mutate({ id: clinicId, isQueueOpen: !clinic?.isQueueOpen })}
- disabled={toggleQueue.isPending}
- >
- {clinic?.isQueueOpen ? <> {t("queue.closeShort")}> : <> {t("queue.openShort")}>}
-
-
-
-
-
- {/* ─── Left: Controls / QR / Stats ─────────────── */}
-
- {/* Actions */}
-
-
{t("queue.actions")}
-
- {members.length > 0 && (
-
-
-
- Praticien assigné
-
-
- setPractitionerForCall(e.target.value ? Number(e.target.value) : null)
- }
- className="w-full rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm focus:outline-none focus:border-emerald-400"
- aria-label="Praticien assigné"
- >
- — Sans assignation —
- {members.map((m) => (
-
- {m.displayName ?? m.name ?? m.email ?? `Praticien #${m.id}`}
-
- ))}
-
-
- )}
-
-
- callNext.mutate({
- clinicId,
- ...(practitionerForCall ? { practitionerId: practitionerForCall } : {}),
- })
- }
- disabled={callNext.isPending || waiting.length === 0}
- >
- {callNext.isPending ? : }
- {t("queue.callNext")}
-
-
printTicket.mutate({ clinicId })}
- disabled={printTicket.isPending || !clinic?.isQueueOpen}
- >
- {t("queue.printTicket")}
-
-
setConfirmReset(true)}
- disabled={reset.isPending}
- >
- {t("queue.resetQueue")}
-
- {confirmReset && (
-
-
{t("queue.resetConfirm")}
-
- { reset.mutate({ clinicId }); setConfirmReset(false); }} disabled={reset.isPending}>
- {t("queue.resetYes")}
-
- setConfirmReset(false)}>{t("common.cancel")}
-
-
- )}
-
-
- {/* QR */}
-
-
{t("queue.qrCode")}
- {qrQuery.data ? (
-
-
-
- {t("queue.qrExpires")} : {qrQuery.data.qrTokenExpiresAt ? formatTime(qrQuery.data.qrTokenExpiresAt) : "—"}
-
-
-
regenQr.mutate({ id: clinicId })} disabled={regenQr.isPending}>
- {regenQr.isPending ? : } {t("queue.qrRenew")}
-
-
navigate(`/dashboard/poster/${clinicId}`)}>
- {t("queue.qrPoster")}
-
-
-
- ) : (
-
-
-
- )}
-
-
- {/* Stats */}
-
-
{t("queue.statsTitle")}
-
- {[
- { label: t("queue.waiting"), value: waiting.length, icon: Users },
- { label: t("queue.called"), value: called.length, icon: Play },
- { label: t("queue.statsAvgConsult"), value: t("queue.statsAvgConsultValue", { minutes: clinic?.avgConsultationMinutes ?? 15 }), icon: Clock },
- ].map((s) => {
- const Icon = s.icon;
- return (
-
-
- {s.label}
-
-
{s.value}
-
- );
- })}
-
-
-
-
- {/* ─── Right: Queue list ───────────────────────── */}
-
-
-
-
{t("queue.queueListTitle")}
-
- {members.length > 0 && (
-
-
- Filtre
-
- setPractitionerFilter(null)}
- className={`px-2.5 py-1 rounded-lg text-xs font-medium border transition-all ${
- practitionerFilter === null
- ? "bg-teal-600 text-white border-teal-600"
- : "bg-white border-slate-200 text-slate-600 hover:border-emerald-400"
- }`}
- >
- Tous
-
- {members.map((m) => (
- setPractitionerFilter(m.id)}
- className={`flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium border transition-all ${
- practitionerFilter === m.id
- ? "text-white border-transparent shadow-md"
- : "bg-white border-slate-200 text-slate-700 hover:border-emerald-400"
- }`}
- style={
- practitionerFilter === m.id
- ? { background: m.color ?? "#10b981" }
- : undefined
- }
- >
-
- {m.displayName ?? m.name ?? m.email ?? `#${m.id}`}
-
- ))}
-
- )}
-
{t("queue.patientCount", { count: queue.length })}
-
-
-
- {queueQuery.isLoading ? (
-
-
-
- ) : queue.length === 0 ? (
-
-
-
{t("queue.noPatients")}
- {!clinic?.isQueueOpen && (
-
{t("queue.openToWelcome")}
- )}
-
- ) : (
-
- {queue.map((entry) => {
- const draggable = entry.status === "waiting";
- return (
-
draggable && setDragId(entry.id)}
- onDragOver={(e) => { if (draggable) { e.preventDefault(); setDragOverId(entry.id); } }}
- onDragLeave={() => setDragOverId((id) => (id === entry.id ? null : id))}
- onDrop={() => draggable && handleDrop(entry.id)}
- className={`flex items-center gap-3 p-4 transition-all ${
- entry.status === "called"
- ? "bg-emerald-50/60"
- : entry.status === "in_consultation"
- ? "bg-cyan-50/40"
- : "hover:bg-emerald-50/30"
- } ${dragOverId === entry.id ? "ring-2 ring-emerald-400" : ""} ${draggable ? "cursor-move" : ""}`}
- >
- {/* Ticket */}
-
- {formatTicket(entry.ticketNumber)}
-
-
- {/* Info */}
-
-
-
- {entry.patientName ?? t("queue.patientFallback", { number: entry.ticketNumber })}
-
- {entry.isPrinted && (
- {t("queue.printed")}
- )}
- {entry.practitionerId && memberById.get(entry.practitionerId) && (
-
-
- {memberById.get(entry.practitionerId)?.displayName ??
- memberById.get(entry.practitionerId)?.name ??
- `#${entry.practitionerId}`}
-
- )}
-
-
- {t("queue.posShort")} {entry.position}
- ·
- ~{entry.estimatedWaitMinutes ?? "?"} {t("queue.minShort")}
- ·
- {formatTime(entry.joinedAt)}
-
-
-
- {/* Status */}
-
-
- {/* Actions */}
-
- {entry.status === "waiting" && (
-
- callSpecific.mutate({
- entryId: entry.id,
- ...(practitionerForCall
- ? { practitionerId: practitionerForCall }
- : {}),
- })
- }
- className="w-8 h-8 rounded-lg flex items-center justify-center text-emerald-600 hover:bg-emerald-100"
- title={t("queue.callThisPatient")}
- >
-
-
- )}
- {(entry.status === "called" || entry.status === "in_consultation") && (
-
markDone.mutate({ entryId: entry.id })}
- className="w-8 h-8 rounded-lg flex items-center justify-center text-emerald-600 hover:bg-emerald-100"
- title={t("queue.endConsultation")}
- >
-
-
- )}
- {(entry.status === "waiting" || entry.status === "called") && (
-
markAbsent.mutate({ entryId: entry.id })}
- className="w-8 h-8 rounded-lg flex items-center justify-center text-orange-600 hover:bg-orange-100"
- title={t("queue.markAbsentTitle")}
- >
-
-
- )}
-
-
- );
- })}
-
- )}
-
-
-
-
- );
-}
-
-function StatusBadge({ status }: { status: QueueEntryStatus }) {
- const { t } = useTranslation();
- const map: Record = {
- waiting: { label: t("queue.statusWaiting"), className: "badge-waiting" },
- called: { label: t("queue.statusCalled"), className: "badge-called" },
- in_consultation: { label: t("queue.statusInConsultation"), className: "badge-called" },
- done: { label: t("queue.statusDone"), className: "badge-done" },
- absent: { label: t("queue.statusAbsent"), className: "badge-absent" },
- canceled: { label: t("queue.statusCanceled"), className: "badge-absent" },
- };
- const m = map[status];
- return {m.label} ;
-}
diff --git a/client/src/pages/ResetPassword.tsx b/client/src/pages/ResetPassword.tsx
deleted file mode 100644
index f932092..0000000
--- a/client/src/pages/ResetPassword.tsx
+++ /dev/null
@@ -1,146 +0,0 @@
-import { useState } from "react";
-import { Link, useLocation, useRoute } from "wouter";
-import { Helmet } from "react-helmet-async";
-import { useTranslation } from "react-i18next";
-import { Stethoscope, Lock, ArrowLeft, Loader2, CheckCircle2, AlertCircle } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { trpc } from "@/lib/trpc";
-
-export default function ResetPassword() {
- const { t } = useTranslation();
- const [, navigate] = useLocation();
- const [, params] = useRoute<{ token: string }>("/reset-password/:token");
- const token = params?.token ?? "";
- const [password, setPassword] = useState("");
- const [confirm, setConfirm] = useState("");
- const [error, setError] = useState(null);
- const [success, setSuccess] = useState(false);
-
- const reset = trpc.auth.resetPassword.useMutation({
- onSuccess: () => {
- setSuccess(true);
- setTimeout(() => navigate("/login"), 2000);
- },
- onError: (err) => setError(err.message),
- });
-
- const handleSubmit = (e: React.FormEvent) => {
- e.preventDefault();
- setError(null);
- if (password !== confirm) {
- setError(t("reset.errorMismatch"));
- return;
- }
- if (password.length < 8) {
- setError(t("reset.errorTooShort"));
- return;
- }
- reset.mutate({ token, newPassword: password });
- };
-
- return (
-
-
- {t("reset.metaTitle")}
-
-
-
-
-
-
-
-
- {t("reset.backToLogin")}
-
-
-
-
-
-
- {t("reset.title")}
-
-
{t("reset.subtitle")}
-
-
-
- {success ? (
-
-
-
{t("reset.successTitle")}
-
{t("reset.successMessage")}
-
- ) : (
-
- )}
-
-
-
- );
-}
diff --git a/client/src/pages/SubscriptionBlocked.tsx b/client/src/pages/SubscriptionBlocked.tsx
deleted file mode 100644
index bc3adca..0000000
--- a/client/src/pages/SubscriptionBlocked.tsx
+++ /dev/null
@@ -1,140 +0,0 @@
-import { Button } from "@/components/ui/button";
-import { useLocation } from "wouter";
-import { Helmet } from "react-helmet-async";
-import { useTranslation } from "react-i18next";
-import { Lock, CreditCard, CheckCircle2, Loader2, AlertTriangle } from "lucide-react";
-import { trpc } from "@/lib/trpc";
-import { toast } from "sonner";
-
-export default function SubscriptionBlocked() {
- const { t, i18n } = useTranslation();
- const [, navigate] = useLocation();
- const planQuery = trpc.subscription.getCurrentPlan.useQuery();
- const checkQuery = trpc.subscription.check.useQuery();
-
- const portalMutation = trpc.subscription.createPortalSession.useMutation({
- onSuccess: ({ url }) => {
- window.location.href = url;
- },
- onError: (e) => toast.error(e.message),
- });
-
- const features = [
- t("subscriptionBlocked.features.0"),
- t("subscriptionBlocked.features.1"),
- t("subscriptionBlocked.features.2"),
- t("subscriptionBlocked.features.3"),
- ];
-
- const plan = planQuery.data;
- const check = checkQuery.data;
- const planName = plan?.plan ?? "—";
- const status = plan?.status ?? null;
- const trialEnd = plan?.trialEndsAt ? new Date(plan.trialEndsAt) : null;
- const periodEnd = plan?.currentPeriodEnd ? new Date(plan.currentPeriodEnd) : null;
- const locale = i18n.language === "en" ? "en-US" : "fr-FR";
- const hasActiveSub = plan?.hasActiveSubscription ?? false;
- const stripeReady = plan?.stripeConfigured ?? false;
- const daysLeft = check?.daysRemaining ?? 0;
-
- return (
-
-
- {t("subscriptionBlocked.metaTitle")}
-
-
-
-
-
-
-
-
-
{t("subscriptionBlocked.title")}
-
- {/* Live plan status */}
-
-
- Plan
- {planName}
-
-
- Statut
-
- {status === "trialing"
- ? t("subscription.trial")
- : status === "active"
- ? t("subscription.active")
- : status ?? t("subscription.expired")}
-
-
- {status === "trialing" && trialEnd && (
-
- Fin d'essai
-
- {trialEnd.toLocaleDateString(locale)}
- {daysLeft > 0 && (
-
- ({t("subscription.daysCount", { count: daysLeft })})
-
- )}
-
-
- )}
- {status === "active" && periodEnd && (
-
- Renouvellement
- {periodEnd.toLocaleDateString(locale)}
-
- )}
-
-
-
- {t("subscriptionBlocked.description")}
-
-
- {features.map((f) => (
-
-
- {f}
-
- ))}
-
-
- {!stripeReady && (
-
-
-
- Le paiement n'est pas configuré sur ce serveur. Contactez l'administrateur.
-
-
- )}
-
- {hasActiveSub ? (
-
portalMutation.mutate()}
- disabled={portalMutation.isPending || !stripeReady}
- className="w-full bg-primary text-primary-foreground hover:bg-primary/90 glow-teal h-12 font-semibold"
- >
- {portalMutation.isPending ? (
-
- ) : (
-
- )}
- Gérer l'abonnement
-
- ) : (
-
navigate("/dashboard/subscription")}
- className="w-full bg-primary text-primary-foreground hover:bg-primary/90 glow-teal h-12 font-semibold"
- >
- {t("subscriptionBlocked.cta")}
-
- )}
-
-
-
- );
-}
diff --git a/client/src/pages/SubscriptionCancel.tsx b/client/src/pages/SubscriptionCancel.tsx
deleted file mode 100644
index 6a8cfc1..0000000
--- a/client/src/pages/SubscriptionCancel.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import { useLocation } from "wouter";
-import { Helmet } from "react-helmet-async";
-import { XCircle } from "lucide-react";
-import { Button } from "@/components/ui/button";
-
-export default function SubscriptionCancel() {
- const [, navigate] = useLocation();
-
- return (
-
-
- Paiement annulé — QueueMed
-
-
-
-
-
-
Paiement annulé
-
- Aucun montant n'a été prélevé. Vous pouvez réessayer à tout moment ou
- continuer à utiliser votre essai.
-
-
- navigate("/dashboard")}
- >
- Tableau de bord
-
- navigate("/dashboard/subscription")}
- >
- Retour aux plans
-
-
-
-
- );
-}
diff --git a/client/src/pages/SubscriptionPage.tsx b/client/src/pages/SubscriptionPage.tsx
deleted file mode 100644
index 195f08c..0000000
--- a/client/src/pages/SubscriptionPage.tsx
+++ /dev/null
@@ -1,371 +0,0 @@
-import { Helmet } from "react-helmet-async";
-import { useTranslation } from "react-i18next";
-import {
- Check, Sparkles, Clock, Loader2, AlertTriangle,
- TrendingUp, Crown, Heart, Settings,
-} from "lucide-react";
-import { trpc } from "@/lib/trpc";
-import { Button } from "@/components/ui/button";
-import { toast } from "sonner";
-
-const STRIPE_BASIC_PRICE_ID = import.meta.env.VITE_STRIPE_BASIC_PRICE_ID as
- | string
- | undefined;
-const STRIPE_PRO_PRICE_ID = import.meta.env.VITE_STRIPE_PRO_PRICE_ID as
- | string
- | undefined;
-
-export default function SubscriptionPage() {
- const { t, i18n } = useTranslation();
- const subQuery = trpc.subscription.get.useQuery();
- const checkQuery = trpc.subscription.check.useQuery();
- const planQuery = trpc.subscription.getCurrentPlan.useQuery();
-
- const checkoutMutation = trpc.subscription.createCheckoutSession.useMutation({
- onSuccess: ({ url }) => {
- window.location.href = url;
- },
- onError: (e) => toast.error(e.message),
- });
-
- const portalMutation = trpc.subscription.createPortalSession.useMutation({
- onSuccess: ({ url }) => {
- window.location.href = url;
- },
- onError: (e) => toast.error(e.message),
- });
-
- const PLANS = [
- {
- plan: "trial" as const,
- name: t("subscription.plans.trial.name"),
- price: "0€",
- period: t("subscription.plans.trial.period"),
- description: t("subscription.plans.trial.description"),
- features: [
- t("subscription.plans.trial.features.0"),
- t("subscription.plans.trial.features.1"),
- t("subscription.plans.trial.features.2"),
- t("subscription.plans.trial.features.3"),
- ],
- icon: Sparkles,
- color: "from-slate-500 to-slate-600",
- priceId: undefined as string | undefined,
- },
- {
- plan: "basic" as const,
- name: t("subscription.plans.basic.name"),
- price: "29€",
- period: t("subscription.plans.basic.period"),
- description: t("subscription.plans.basic.description"),
- features: [
- t("subscription.plans.basic.features.0"),
- t("subscription.plans.basic.features.1"),
- t("subscription.plans.basic.features.2"),
- t("subscription.plans.basic.features.3"),
- t("subscription.plans.basic.features.4"),
- ],
- icon: TrendingUp,
- color: "from-emerald-500 to-teal-500",
- highlighted: true,
- priceId: STRIPE_BASIC_PRICE_ID,
- },
- {
- plan: "pro" as const,
- name: t("subscription.plans.pro.name"),
- price: "79€",
- period: t("subscription.plans.pro.period"),
- description: t("subscription.plans.pro.description"),
- features: [
- t("subscription.plans.pro.features.0"),
- t("subscription.plans.pro.features.1"),
- t("subscription.plans.pro.features.2"),
- t("subscription.plans.pro.features.3"),
- t("subscription.plans.pro.features.4"),
- ],
- icon: Crown,
- color: "from-violet-500 to-fuchsia-500",
- priceId: STRIPE_PRO_PRICE_ID,
- },
- ];
-
- const sub = subQuery.data;
- const check = checkQuery.data;
- const plan = planQuery.data;
-
- const stripeReady = plan?.stripeConfigured ?? false;
- const hasActiveSub = plan?.hasActiveSubscription ?? false;
- const checkoutBusy = checkoutMutation.isPending;
- const portalBusy = portalMutation.isPending;
-
- const handleSubscribe = (planKey: "basic" | "pro", priceId: string | undefined) => {
- if (!stripeReady) {
- toast.error(
- "Le paiement Stripe n'est pas configuré sur ce serveur. Contactez l'administrateur."
- );
- return;
- }
- if (!priceId) {
- toast.error(
- `Identifiant de prix manquant pour le plan ${planKey}. Configurez VITE_STRIPE_${planKey === "basic" ? "BASIC" : "PRO"}_PRICE_ID.`
- );
- return;
- }
- checkoutMutation.mutate({ priceId });
- };
-
- const handleManage = () => {
- if (!stripeReady) {
- toast.error(
- "Le paiement Stripe n'est pas configuré sur ce serveur. Contactez l'administrateur."
- );
- return;
- }
- portalMutation.mutate();
- };
-
- if (subQuery.isLoading || planQuery.isLoading) {
- return (
-
-
-
- );
- }
-
- const isTrialing = sub?.status === "trialing";
- const isActive = sub?.status === "active";
- const daysLeft = check?.daysRemaining ?? 0;
- const expired = !check?.active;
- const locale = i18n.language === "en" ? "en-US" : "fr-FR";
-
- return (
-
-
- {t("subscription.metaTitle")}
-
-
-
-
{t("subscription.title")}
-
{t("subscription.subtitle")}
-
-
- {!stripeReady && (
-
-
-
- Paiement Stripe non configuré. {" "}
- L'application fonctionne normalement, mais les abonnements payants ne sont
- pas activés sur ce serveur. Définissez STRIPE_SECRET_KEY et{" "}
- STRIPE_WEBHOOK_SECRET côté serveur, ainsi que les IDs de prix
- côté client (VITE_STRIPE_BASIC_PRICE_ID,{" "}
- VITE_STRIPE_PRO_PRICE_ID).
-
-
- )}
-
- {/* Current status */}
-
- {!expired && (
-
- )}
-
-
-
-
{t("subscription.currentPlan")}
-
-
{sub?.plan ?? "—"}
-
- {expired ? t("subscription.expired") : isTrialing ? t("subscription.trial") : isActive ? t("subscription.active") : sub?.status}
-
-
- {expired ? (
-
-
- {t("subscription.expiredMessage")}
-
- ) : (
-
-
- {isTrialing ? t("subscription.freeTrial") : t("subscription.nextRenewal")} {t("subscription.in")} {t("subscription.daysCount", { count: daysLeft })}
- {sub?.trialEndsAt && isTrialing && (
- {t("subscription.untilDate", { date: new Date(sub.trialEndsAt).toLocaleDateString(locale) })}
- )}
- {sub?.currentPeriodEnd && isActive && (
- {t("subscription.untilDate", { date: new Date(sub.currentPeriodEnd).toLocaleDateString(locale) })}
- )}
-
- )}
-
-
-
- {hasActiveSub && (
-
- {portalBusy ? (
-
- ) : (
-
- )}
- Gérer l'abonnement
-
- )}
- {(isTrialing || expired) && (
- handleSubscribe("basic", STRIPE_BASIC_PRICE_ID)}
- disabled={checkoutBusy || !stripeReady}
- >
- {checkoutBusy ? (
-
- ) : (
-
- )}
- {t("subscription.subscribeNow")}
-
- )}
-
-
-
- {isTrialing && daysLeft > 0 && (
-
-
- {t("subscription.dayN", { day: 30 - daysLeft })}
- {t("subscription.daysLeft", { days: daysLeft })}
-
-
-
- )}
-
-
- {/* Plans grid */}
-
{t("subscription.choosePlan")}
-
- {PLANS.map((p) => {
- const Icon = p.icon;
- const isCurrent = sub?.plan === p.plan;
- const canCheckout = p.plan !== "trial" && stripeReady && !!p.priceId;
- return (
-
- {p.highlighted && (
-
- {t("subscription.popular")}
-
- )}
- {isCurrent && (
-
- {t("subscription.current")}
-
- )}
-
-
-
-
-
{p.name}
-
{p.description}
-
- {p.price}
- {p.period}
-
-
- {p.features.map((f) => (
-
-
- {f}
-
- ))}
-
- {p.plan === "trial" ? (
-
- {isCurrent ? t("subscription.currentPlanLabel") : t("subscription.automaticTrial")}
-
- ) : isCurrent && hasActiveSub ? (
-
- {portalBusy ? (
-
- ) : (
-
- )}
- Gérer l'abonnement
-
- ) : (
-
handleSubscribe(p.plan as "basic" | "pro", p.priceId)}
- disabled={checkoutBusy || !canCheckout}
- >
- {checkoutBusy ? (
-
- ) : null}
- {t("subscription.subscribe")}
-
- )}
-
- );
- })}
-
-
- {/* Guarantee */}
-
-
-
{t("subscription.commitmentTitle")}
-
- {t("subscription.commitmentBody")}
-
-
-
- );
-}
diff --git a/client/src/pages/SubscriptionSuccess.tsx b/client/src/pages/SubscriptionSuccess.tsx
deleted file mode 100644
index 6dd1beb..0000000
--- a/client/src/pages/SubscriptionSuccess.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { useEffect } from "react";
-import { useLocation } from "wouter";
-import { Helmet } from "react-helmet-async";
-import { CheckCircle2, Sparkles } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { trpc } from "@/lib/trpc";
-
-export default function SubscriptionSuccess() {
- const [, navigate] = useLocation();
- const utils = trpc.useUtils();
-
- useEffect(() => {
- // Refresh subscription data so the dashboard reflects the new plan immediately.
- utils.subscription.get.invalidate();
- utils.subscription.check.invalidate();
- utils.subscription.getCurrentPlan.invalidate();
-
- const t = setTimeout(() => navigate("/dashboard/subscription"), 5000);
- return () => clearTimeout(t);
- }, [navigate, utils]);
-
- return (
-
-
- Paiement confirmé — QueueMed
-
-
-
-
-
-
Merci pour votre abonnement !
-
- Votre paiement a été confirmé avec succès.
-
-
-
- Redirection automatique dans quelques secondes…
-
-
- navigate("/dashboard/subscription")}
- >
- Voir mon abonnement
-
- navigate("/dashboard")}
- >
- Aller au tableau de bord
-
-
-
-
- );
-}
diff --git a/client/src/pages/WhatsAppSetup.tsx b/client/src/pages/WhatsAppSetup.tsx
deleted file mode 100644
index fb70efe..0000000
--- a/client/src/pages/WhatsAppSetup.tsx
+++ /dev/null
@@ -1,424 +0,0 @@
-import { useState, useEffect, useRef } from "react";
-import { Helmet } from "react-helmet-async";
-import { useTranslation } from "react-i18next";
-import { trpc } from "@/lib/trpc";
-import { useAuth } from "@/_core/hooks/useAuth";
-import Layout from "@/components/Layout";
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Badge } from "@/components/ui/badge";
-import { Alert, AlertDescription } from "@/components/ui/alert";
-import { Separator } from "@/components/ui/separator";
-import { toast } from "sonner";
-import {
- MessageSquare,
- Wifi,
- WifiOff,
- QrCode,
- RefreshCw,
- LogOut,
- Send,
- CheckCircle,
- AlertCircle,
- Loader2,
- Info,
- Smartphone,
-} from "lucide-react";
-import CountryCodeManager from "@/components/CountryCodeManager";
-import WhatsAppTemplateEditor from "@/components/WhatsAppTemplateEditor";
-
-type WAStatus = "disconnected" | "connecting" | "qr_ready" | "connected";
-
-export default function WhatsAppSetup() {
- const { t } = useTranslation();
- const { user } = useAuth();
- const utils = trpc.useUtils();
-
- const [selectedClinicId, setSelectedClinicId] = useState(null);
- const [testPhone, setTestPhone] = useState("");
- const [pollingActive, setPollingActive] = useState(false);
- const pollRef = useRef | null>(null);
-
- const STATUS_CONFIG: Record = {
- disconnected: {
- label: t("whatsapp.statusDisconnected"),
- color: "bg-gray-500/20 text-gray-400 border-gray-500/30",
- icon: ,
- },
- connecting: {
- label: t("whatsapp.statusConnecting"),
- color: "bg-yellow-500/20 text-yellow-400 border-yellow-500/30",
- icon: ,
- },
- qr_ready: {
- label: t("whatsapp.statusQrReady"),
- color: "bg-blue-500/20 text-blue-400 border-blue-500/30",
- icon: ,
- },
- connected: {
- label: t("whatsapp.statusConnected"),
- color: "bg-emerald-500/20 text-emerald-400 border-emerald-500/30",
- icon: ,
- },
- };
-
- const { data: clinics = [] } = trpc.clinic.list.useQuery();
-
- const { data: waStatus, refetch: refetchStatus } = trpc.whatsapp.status.useQuery(
- { clinicId: selectedClinicId ?? 0 },
- { enabled: !!selectedClinicId, refetchInterval: pollingActive ? 3000 : false }
- );
-
- const connectMut = trpc.whatsapp.connect.useMutation({
- onSuccess: (data) => {
- utils.whatsapp.status.invalidate();
- if (data.status === "qr_ready") {
- setPollingActive(true);
- toast.info(t("whatsapp.toastQrGenerated"));
- } else if (data.status === "connected") {
- setPollingActive(false);
- toast.success(t("whatsapp.toastConnected"));
- }
- },
- onError: (err) => toast.error(err.message),
- });
-
- const disconnectMut = trpc.whatsapp.disconnect.useMutation({
- onSuccess: () => {
- setPollingActive(false);
- utils.whatsapp.status.invalidate();
- toast.success(t("whatsapp.toastDisconnected"));
- },
- onError: (err) => toast.error(err.message),
- });
-
- const testMut = trpc.whatsapp.sendTest.useMutation({
- onSuccess: (data) => {
- if (data.success) toast.success(t("whatsapp.toastTestSent"));
- else toast.error(t("whatsapp.toastTestFailed", { error: data.error ?? "" }));
- },
- onError: (err) => toast.error(err.message),
- });
-
- // Stop polling once connected
- useEffect(() => {
- if (waStatus?.status === "connected") {
- setPollingActive(false);
- }
- }, [waStatus?.status]);
-
- // Auto-select first clinic
- useEffect(() => {
- if (clinics.length > 0 && !selectedClinicId) {
- setSelectedClinicId(clinics[0].id);
- }
- }, [clinics, selectedClinicId]);
-
- const handleConnect = () => {
- if (!selectedClinicId) return;
- connectMut.mutate({ clinicId: selectedClinicId });
- };
-
- const handleDisconnect = () => {
- if (!selectedClinicId) return;
- disconnectMut.mutate({ clinicId: selectedClinicId });
- };
-
- const handleTest = () => {
- if (!selectedClinicId || !testPhone.trim()) return;
- testMut.mutate({ clinicId: selectedClinicId, phone: testPhone.trim() });
- };
-
- const status: WAStatus = waStatus?.status ?? "disconnected";
- const cfg = STATUS_CONFIG[status];
-
- return (
-
-
- {t("whatsapp.metaTitle")}
-
-
-
- {/* Header */}
-
-
-
-
-
-
{t("whatsapp.headerTitle")}
-
- {t("whatsapp.headerSubtitle")}
-
-
-
-
- {/* Disclaimer */}
-
-
-
- {t("whatsapp.disclaimerNote")} {t("whatsapp.disclaimerBody")}
-
-
-
- {/* Clinic selector */}
- {clinics.length > 1 && (
-
-
- {t("whatsapp.clinic")}
-
-
-
- {clinics.map((c) => (
- setSelectedClinicId(c.id)}
- >
- {c.name}
-
- ))}
-
-
-
- )}
-
- {/* Status card */}
-
-
-
-
-
- {t("whatsapp.connectionStatus")}
-
-
- {cfg.icon}
- {cfg.label}
-
-
-
-
- {/* QR Code display */}
- {status === "qr_ready" && waStatus?.qrCode && (
-
-
-
-
-
-
-
- {t("whatsapp.howToScan")}
-
-
- {t("whatsapp.scanStep1")}
- {t("whatsapp.scanStep2")}
- {t("whatsapp.scanStep3")}
- {t("whatsapp.scanStep4")}
-
-
-
refetchStatus()}
- className="gap-2"
- >
-
- {t("whatsapp.refreshStatus")}
-
-
- )}
-
- {/* Connected state */}
- {status === "connected" && (
-
-
-
-
{t("whatsapp.connectedTitle")}
-
- {t("whatsapp.connectedBody")}
-
-
-
- )}
-
- {/* Disconnected state */}
- {(status === "disconnected") && (
-
-
-
-
{t("whatsapp.notConnectedTitle")}
-
- {t("whatsapp.notConnectedBody")}
-
-
-
- )}
-
- {/* Action buttons */}
-
- {status === "disconnected" && (
-
- {connectMut.isPending ? (
-
- ) : (
-
- )}
- {t("whatsapp.connect")}
-
- )}
-
- {status === "qr_ready" && (
- <>
-
-
- {t("whatsapp.newQr")}
-
-
-
- {t("whatsapp.cancel")}
-
- >
- )}
-
- {status === "connecting" && (
-
-
- {t("whatsapp.statusConnecting")}
-
- )}
-
- {status === "connected" && (
-
- {disconnectMut.isPending ? (
-
- ) : (
-
- )}
- {t("whatsapp.disconnect")}
-
- )}
-
-
-
-
- {/* Test message */}
- {status === "connected" && (
-
-
-
-
- {t("whatsapp.testMessage")}
-
-
- {t("whatsapp.testMessageHelp")}
-
-
-
-
- setTestPhone(e.target.value)}
- className="flex-1"
- aria-label={t("whatsapp.testPhoneLabel")}
- />
-
- {testMut.isPending ? (
-
- ) : (
-
- )}
- {t("whatsapp.send")}
-
-
-
- {t("whatsapp.phoneFormatHint")}
-
-
-
- )}
-
- {/* WhatsApp message templates */}
- {selectedClinicId && (
- <>
-
-
- >
- )}
-
-
-
- {/* Country code management (owner/admin only) */}
-
-
-
-
- {/* How it works */}
-
-
- {t("whatsapp.howItWorks")}
-
-
-
- {[
- {
- step: "1",
- title: t("whatsapp.step1Title"),
- desc: t("whatsapp.step1Desc"),
- color: "text-teal-400",
- },
- {
- step: "2",
- title: t("whatsapp.step2Title"),
- desc: t("whatsapp.step2Desc"),
- color: "text-orange-400",
- },
- {
- step: "3",
- title: t("whatsapp.step3Title"),
- desc: t("whatsapp.step3Desc"),
- color: "text-emerald-400",
- },
- ].map((item) => (
-
-
{item.step}
-
-
{item.title}
-
{item.desc}
-
-
- ))}
-
-
-
-
-
- );
-}
diff --git a/client/src/styles.css b/client/src/styles.css
deleted file mode 100644
index 9085be7..0000000
--- a/client/src/styles.css
+++ /dev/null
@@ -1,238 +0,0 @@
-@import "tailwindcss";
-
-@theme {
- --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
- --font-display: "Inter", system-ui, -apple-system, sans-serif;
-
- --color-background: #ffffff;
- --color-foreground: #0f172a;
-
- --color-card: #ffffff;
- --color-card-foreground: #0f172a;
-
- --color-popover: #ffffff;
- --color-popover-foreground: #0f172a;
-
- --color-primary: #0d9488;
- --color-primary-foreground: #ffffff;
-
- --color-secondary: #06b6d4;
- --color-secondary-foreground: #ffffff;
-
- --color-accent: #10b981;
- --color-accent-foreground: #ffffff;
-
- --color-muted: #f1f5f9;
- --color-muted-foreground: #64748b;
-
- --color-destructive: #ef4444;
- --color-destructive-foreground: #ffffff;
-
- --color-warning: #f97316;
- --color-warning-foreground: #ffffff;
-
- --color-border: #e2e8f0;
- --color-input: #e2e8f0;
- --color-ring: #10b981;
-
- --radius-lg: 0.75rem;
- --radius-xl: 1rem;
- --radius-2xl: 1.25rem;
- --radius-3xl: 1.75rem;
-}
-
-html, body, #root {
- height: 100%;
- min-height: 100%;
-}
-
-body {
- background-color: #ffffff;
- background-image:
- radial-gradient(at 0% 0%, rgba(16, 185, 129, 0.08) 0px, transparent 50%),
- radial-gradient(at 100% 0%, rgba(6, 182, 212, 0.08) 0px, transparent 50%),
- radial-gradient(at 50% 100%, rgba(16, 185, 129, 0.04) 0px, transparent 60%);
- color: #0f172a;
- font-family: "Inter", system-ui, sans-serif;
- -webkit-font-smoothing: antialiased;
-}
-
-/* ─── Glass cards ─────────────────────────────────────────────────────────── */
-.glass-card {
- background-color: rgba(255, 255, 255, 0.72);
- backdrop-filter: blur(14px);
- -webkit-backdrop-filter: blur(14px);
- border: 1px solid rgba(255, 255, 255, 0.6);
- box-shadow:
- 0 1px 2px rgba(15, 118, 110, 0.04),
- 0 8px 32px rgba(13, 148, 136, 0.06);
-}
-
-.glass-card-strong {
- background-color: rgba(255, 255, 255, 0.95);
- backdrop-filter: blur(18px);
- -webkit-backdrop-filter: blur(18px);
- border: 1px solid rgba(15, 118, 110, 0.08);
- box-shadow:
- 0 1px 2px rgba(15, 118, 110, 0.04),
- 0 12px 48px rgba(13, 148, 136, 0.08);
-}
-
-/* ─── Gradients ────────────────────────────────────────────────────────────── */
-.gradient-text {
- background: linear-gradient(135deg, #10b981 0%, #06b6d4 50%, #0d9488 100%);
- -webkit-background-clip: text;
- background-clip: text;
- color: transparent;
- -webkit-text-fill-color: transparent;
-}
-
-.gradient-bg {
- background: linear-gradient(135deg, #34d399 0%, #22d3ee 50%, #2dd4bf 100%);
-}
-
-.gradient-bg-soft {
- background: linear-gradient(135deg, #ecfdf5 0%, #ecfeff 100%);
-}
-
-/* ─── Glow effects ─────────────────────────────────────────────────────────── */
-.glow-teal {
- box-shadow:
- 0 0 0 1px rgba(13, 148, 136, 0.15),
- 0 8px 24px rgba(13, 148, 136, 0.18);
-}
-
-.glow-emerald {
- box-shadow:
- 0 0 0 1px rgba(16, 185, 129, 0.15),
- 0 10px 28px rgba(16, 185, 129, 0.22);
-}
-
-/* ─── Status badges (queue) ────────────────────────────────────────────────── */
-.badge-waiting {
- display: inline-flex;
- align-items: center;
- padding: 0.125rem 0.625rem;
- border-radius: 9999px;
- font-size: 0.7rem;
- font-weight: 600;
- background-color: rgb(207 250 254);
- color: rgb(14 116 144);
- border: 1px solid rgb(165 243 252);
-}
-
-.badge-called {
- display: inline-flex;
- align-items: center;
- padding: 0.125rem 0.625rem;
- border-radius: 9999px;
- font-size: 0.7rem;
- font-weight: 600;
- background-color: rgb(209 250 229);
- color: rgb(4 120 87);
- border: 1px solid rgb(167 243 208);
-}
-
-.badge-done {
- display: inline-flex;
- align-items: center;
- padding: 0.125rem 0.625rem;
- border-radius: 9999px;
- font-size: 0.7rem;
- font-weight: 600;
- background-color: rgb(241 245 249);
- color: rgb(71 85 105);
- border: 1px solid rgb(226 232 240);
-}
-
-.badge-absent {
- display: inline-flex;
- align-items: center;
- padding: 0.125rem 0.625rem;
- border-radius: 9999px;
- font-size: 0.7rem;
- font-weight: 600;
- background-color: rgb(255 237 213);
- color: rgb(154 52 18);
- border: 1px solid rgb(254 215 170);
-}
-
-/* ─── Animations ──────────────────────────────────────────────────────────── */
-@keyframes pulse-glow {
- 0%, 100% {
- opacity: 0.5;
- transform: scale(1);
- }
- 50% {
- opacity: 0.85;
- transform: scale(1.05);
- }
-}
-
-.animate-pulse-glow {
- animation: pulse-glow 4s ease-in-out infinite;
-}
-
-@keyframes shimmer {
- 0% { background-position: -200% 0; }
- 100% { background-position: 200% 0; }
-}
-
-.shimmer {
- background: linear-gradient(
- 90deg,
- rgba(16, 185, 129, 0) 0%,
- rgba(16, 185, 129, 0.15) 50%,
- rgba(16, 185, 129, 0) 100%
- );
- background-size: 200% 100%;
- animation: shimmer 2s infinite;
-}
-
-@keyframes ticker {
- 0% { transform: translateX(100%); }
- 100% { transform: translateX(-100%); }
-}
-
-.animate-ticker {
- animation: ticker 30s linear infinite;
-}
-
-/* ─── Container ───────────────────────────────────────────────────────────── */
-.container {
- width: 100%;
- margin-left: auto;
- margin-right: auto;
- padding-left: 1rem;
- padding-right: 1rem;
-}
-
-@media (min-width: 640px) {
- .container { max-width: 640px; }
-}
-@media (min-width: 768px) {
- .container { max-width: 768px; padding-left: 1.5rem; padding-right: 1.5rem; }
-}
-@media (min-width: 1024px) {
- .container { max-width: 1024px; }
-}
-@media (min-width: 1280px) {
- .container { max-width: 1200px; }
-}
-
-/* ─── Print ───────────────────────────────────────────────────────────────── */
-@media print {
- body { background: white !important; }
- .no-print { display: none !important; }
-}
-
-/* ─── Scrollbar (subtle) ──────────────────────────────────────────────────── */
-::-webkit-scrollbar { width: 8px; height: 8px; }
-::-webkit-scrollbar-track { background: transparent; }
-::-webkit-scrollbar-thumb {
- background: rgba(15, 118, 110, 0.2);
- border-radius: 4px;
-}
-::-webkit-scrollbar-thumb:hover {
- background: rgba(15, 118, 110, 0.35);
-}
diff --git a/client/src/vite-env.d.ts b/client/src/vite-env.d.ts
deleted file mode 100644
index 64251fb..0000000
--- a/client/src/vite-env.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-///
-///
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 79ed1fc..0000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-services:
- db:
- image: mysql:8.4
- restart: unless-stopped
- environment:
- MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword}
- MYSQL_DATABASE: ${MYSQL_DATABASE:-queuemed}
- MYSQL_USER: ${MYSQL_USER:-queuemed}
- MYSQL_PASSWORD: ${MYSQL_PASSWORD:-queuemed}
- volumes:
- - mysql_data:/var/lib/mysql
- command:
- - --character-set-server=utf8mb4
- - --collation-server=utf8mb4_unicode_ci
- healthcheck:
- test:
- ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-rootpassword}"]
- interval: 10s
- timeout: 5s
- retries: 10
- networks:
- - queuemed
-
- app:
- build:
- context: .
- dockerfile: Dockerfile
- restart: unless-stopped
- depends_on:
- db:
- condition: service_healthy
- environment:
- NODE_ENV: production
- PORT: 5000
- DATABASE_URL: mysql://${MYSQL_USER:-queuemed}:${MYSQL_PASSWORD:-queuemed}@db:3306/${MYSQL_DATABASE:-queuemed}
- # JWT_SECRET MUST be provided via .env.docker — there is no insecure fallback.
- JWT_SECRET: ${JWT_SECRET:?JWT_SECRET must be set in .env.docker}
- PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:-}
- WHATSAPP_SESSION_DIR: ${WHATSAPP_SESSION_DIR:-/app/data/whatsapp-sessions}
- # MySQL credentials available to scripts/backup-db.sh inside the container
- MYSQL_HOST: db
- MYSQL_DATABASE: ${MYSQL_DATABASE:-queuemed}
- MYSQL_USER: ${MYSQL_USER:-queuemed}
- MYSQL_PASSWORD: ${MYSQL_PASSWORD:-queuemed}
- volumes:
- - app_data:/app/data
- ports:
- - "5100:5000"
- networks:
- - queuemed
-
-networks:
- queuemed:
- driver: bridge
-
-volumes:
- mysql_data:
- driver: local
- app_data:
- driver: local
diff --git a/docs_ref/schema.ts b/docs/schema.ts
similarity index 100%
rename from docs_ref/schema.ts
rename to docs/schema.ts
diff --git a/drizzle.config.ts b/drizzle.config.ts
deleted file mode 100644
index 8886244..0000000
--- a/drizzle.config.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { defineConfig } from "drizzle-kit";
-
-const databaseUrl = process.env.DATABASE_URL;
-if (!databaseUrl) {
- throw new Error("DATABASE_URL is not set — required by drizzle-kit");
-}
-
-export default defineConfig({
- schema: "./server/schema.ts",
- out: "./drizzle",
- dialect: "mysql",
- dbCredentials: {
- url: databaseUrl,
- },
- verbose: true,
- strict: true,
-});
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 02ced83..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,15390 +0,0 @@
-{
- "name": "queue-med",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "queue-med",
- "version": "1.0.0",
- "dependencies": {
- "@hapi/boom": "^10.0.1",
- "@radix-ui/react-alert-dialog": "^1.1.15",
- "@radix-ui/react-checkbox": "^1.1.3",
- "@radix-ui/react-dialog": "^1.1.4",
- "@radix-ui/react-dropdown-menu": "^2.1.4",
- "@radix-ui/react-label": "^2.1.1",
- "@radix-ui/react-popover": "^1.1.4",
- "@radix-ui/react-progress": "^1.1.1",
- "@radix-ui/react-radio-group": "^1.2.2",
- "@radix-ui/react-select": "^2.1.4",
- "@radix-ui/react-separator": "^1.1.1",
- "@radix-ui/react-slot": "^1.1.1",
- "@radix-ui/react-switch": "^1.1.2",
- "@radix-ui/react-tabs": "^1.1.2",
- "@radix-ui/react-toast": "^1.2.4",
- "@radix-ui/react-tooltip": "^1.1.6",
- "@stripe/stripe-js": "^9.3.1",
- "@tailwindcss/vite": "^4.0.0",
- "@tanstack/react-query": "^5.62.7",
- "@trpc/client": "11.0.0-rc.660",
- "@trpc/react-query": "11.0.0-rc.660",
- "@trpc/server": "11.0.0-rc.660",
- "@types/nodemailer": "^8.0.0",
- "@whiskeysockets/baileys": "7.0.0-rc.9",
- "bcryptjs": "^2.4.3",
- "class-variance-authority": "^0.7.1",
- "clsx": "^2.1.1",
- "cmdk": "^1.0.0",
- "cookie-parser": "^1.4.7",
- "cors": "^2.8.5",
- "date-fns": "^4.1.0",
- "drizzle-orm": "^0.38.2",
- "express": "^4.21.2",
- "express-rate-limit": "^8.4.1",
- "framer-motion": "^11.15.0",
- "helmet": "^8.1.0",
- "i18next": "^26.0.8",
- "i18next-browser-languagedetector": "^8.2.1",
- "input-otp": "^1.4.1",
- "jsonwebtoken": "^9.0.2",
- "lucide-react": "^0.468.0",
- "mysql2": "^3.11.5",
- "nanoid": "^5.0.9",
- "nodemailer": "^8.0.6",
- "p-queue": "^9.1.0",
- "pdfkit": "^0.18.0",
- "pino": "^10.3.1",
- "pino-pretty": "^13.1.3",
- "qrcode": "^1.5.4",
- "qrcode-terminal": "^0.12.0",
- "react": "^19.0.0",
- "react-dom": "^19.0.0",
- "react-helmet-async": "^3.0.0",
- "react-i18next": "^17.0.4",
- "recharts": "^2.15.0",
- "socket.io": "^4.8.1",
- "socket.io-client": "^4.8.1",
- "sonner": "^1.7.1",
- "stripe": "^22.1.0",
- "tailwind-merge": "^2.6.0",
- "tailwindcss": "^4.0.0",
- "twilio": "^6.0.0",
- "vite-plugin-pwa": "^1.2.0",
- "workbox-window": "^7.4.0",
- "wouter": "^3.3.5",
- "zod": "^3.24.1"
- },
- "devDependencies": {
- "@types/bcryptjs": "^2.4.6",
- "@types/cookie-parser": "^1.4.8",
- "@types/cors": "^2.8.17",
- "@types/express": "^4.17.21",
- "@types/jsonwebtoken": "^9.0.7",
- "@types/node": "^22.10.2",
- "@types/pdfkit": "^0.17.6",
- "@types/qrcode": "^1.5.5",
- "@types/react": "^19.0.2",
- "@types/react-dom": "^19.0.2",
- "@types/supertest": "^7.2.0",
- "@vitejs/plugin-react": "^4.3.4",
- "concurrently": "^9.1.1",
- "drizzle-kit": "^0.30.1",
- "supertest": "^7.2.2",
- "tsx": "^4.19.2",
- "typescript": "^5.7.2",
- "vite": "^6.0.0",
- "vitest": "^2.1.8"
- },
- "engines": {
- "node": ">=20"
- }
- },
- "node_modules/@apideck/better-ajv-errors": {
- "version": "0.3.7",
- "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.7.tgz",
- "integrity": "sha512-TajUJwGWbDwkCx/CZi7tRE8PVB7simCvKJfHUsSdvps+aTM/PDPP4gkLmKnc+x3CE//y9i/nj74GqdL/hwk7Iw==",
- "license": "MIT",
- "dependencies": {
- "jsonpointer": "^5.0.1",
- "leven": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "ajv": ">=8"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
- "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.28.5",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
- "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
- "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/remapping": "^2.3.5",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.29.1",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
- "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.27.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
- "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.3"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
- "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz",
- "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/helper-replace-supers": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/traverse": "^7.28.6",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz",
- "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "regexpu-core": "^6.3.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz",
- "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "debug": "^4.4.3",
- "lodash.debounce": "^4.0.8",
- "resolve": "^1.22.11"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz",
- "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.5",
- "@babel/types": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
- "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
- "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
- "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
- "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz",
- "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.1",
- "@babel/helper-wrap-function": "^7.27.1",
- "@babel/traverse": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-replace-supers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz",
- "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
- "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
- "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-wrap-function": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz",
- "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
- "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
- "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.29.0"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz",
- "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/traverse": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz",
- "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz",
- "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz",
- "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/plugin-transform-optional-chaining": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.13.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz",
- "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-proposal-private-property-in-object": {
- "version": "7.21.0-placeholder-for-preset-env.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
- "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-assertions": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz",
- "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
- "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
- "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-arrow-functions": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz",
- "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz",
- "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-remap-async-to-generator": "^7.27.1",
- "@babel/traverse": "^7.29.0"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-async-to-generator": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz",
- "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-remap-async-to-generator": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-block-scoped-functions": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz",
- "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz",
- "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz",
- "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-class-static-block": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz",
- "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.12.0"
- }
- },
- "node_modules/@babel/plugin-transform-classes": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz",
- "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-globals": "^7.28.0",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-replace-supers": "^7.28.6",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-computed-properties": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz",
- "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/template": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz",
- "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/traverse": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-dotall-regex": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz",
- "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.28.5",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-duplicate-keys": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz",
- "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz",
- "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.28.5",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-dynamic-import": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz",
- "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-explicit-resource-management": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz",
- "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/plugin-transform-destructuring": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz",
- "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-export-namespace-from": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz",
- "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-for-of": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz",
- "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-function-name": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz",
- "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/traverse": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-json-strings": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz",
- "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-literals": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz",
- "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz",
- "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-member-expression-literals": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz",
- "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz",
- "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-transforms": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz",
- "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz",
- "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.29.0"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-umd": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz",
- "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-transforms": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz",
- "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.28.5",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-new-target": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz",
- "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz",
- "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-numeric-separator": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz",
- "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-object-rest-spread": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz",
- "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/plugin-transform-destructuring": "^7.28.5",
- "@babel/plugin-transform-parameters": "^7.27.7",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-object-super": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz",
- "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-replace-supers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-optional-catch-binding": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz",
- "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz",
- "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-parameters": {
- "version": "7.27.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz",
- "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-private-methods": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz",
- "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-private-property-in-object": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz",
- "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-property-literals": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz",
- "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-self": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
- "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-source": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
- "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz",
- "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-regexp-modifiers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz",
- "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.28.5",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-reserved-words": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz",
- "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-shorthand-properties": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz",
- "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-spread": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz",
- "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-sticky-regex": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz",
- "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-template-literals": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz",
- "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-typeof-symbol": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz",
- "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-escapes": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz",
- "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-property-regex": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz",
- "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.28.5",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-regex": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz",
- "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-sets-regex": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz",
- "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.28.5",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/preset-env": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.2.tgz",
- "integrity": "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==",
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.29.0",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
- "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
- "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
- "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6",
- "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
- "@babel/plugin-syntax-import-assertions": "^7.28.6",
- "@babel/plugin-syntax-import-attributes": "^7.28.6",
- "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
- "@babel/plugin-transform-arrow-functions": "^7.27.1",
- "@babel/plugin-transform-async-generator-functions": "^7.29.0",
- "@babel/plugin-transform-async-to-generator": "^7.28.6",
- "@babel/plugin-transform-block-scoped-functions": "^7.27.1",
- "@babel/plugin-transform-block-scoping": "^7.28.6",
- "@babel/plugin-transform-class-properties": "^7.28.6",
- "@babel/plugin-transform-class-static-block": "^7.28.6",
- "@babel/plugin-transform-classes": "^7.28.6",
- "@babel/plugin-transform-computed-properties": "^7.28.6",
- "@babel/plugin-transform-destructuring": "^7.28.5",
- "@babel/plugin-transform-dotall-regex": "^7.28.6",
- "@babel/plugin-transform-duplicate-keys": "^7.27.1",
- "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0",
- "@babel/plugin-transform-dynamic-import": "^7.27.1",
- "@babel/plugin-transform-explicit-resource-management": "^7.28.6",
- "@babel/plugin-transform-exponentiation-operator": "^7.28.6",
- "@babel/plugin-transform-export-namespace-from": "^7.27.1",
- "@babel/plugin-transform-for-of": "^7.27.1",
- "@babel/plugin-transform-function-name": "^7.27.1",
- "@babel/plugin-transform-json-strings": "^7.28.6",
- "@babel/plugin-transform-literals": "^7.27.1",
- "@babel/plugin-transform-logical-assignment-operators": "^7.28.6",
- "@babel/plugin-transform-member-expression-literals": "^7.27.1",
- "@babel/plugin-transform-modules-amd": "^7.27.1",
- "@babel/plugin-transform-modules-commonjs": "^7.28.6",
- "@babel/plugin-transform-modules-systemjs": "^7.29.0",
- "@babel/plugin-transform-modules-umd": "^7.27.1",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0",
- "@babel/plugin-transform-new-target": "^7.27.1",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6",
- "@babel/plugin-transform-numeric-separator": "^7.28.6",
- "@babel/plugin-transform-object-rest-spread": "^7.28.6",
- "@babel/plugin-transform-object-super": "^7.27.1",
- "@babel/plugin-transform-optional-catch-binding": "^7.28.6",
- "@babel/plugin-transform-optional-chaining": "^7.28.6",
- "@babel/plugin-transform-parameters": "^7.27.7",
- "@babel/plugin-transform-private-methods": "^7.28.6",
- "@babel/plugin-transform-private-property-in-object": "^7.28.6",
- "@babel/plugin-transform-property-literals": "^7.27.1",
- "@babel/plugin-transform-regenerator": "^7.29.0",
- "@babel/plugin-transform-regexp-modifiers": "^7.28.6",
- "@babel/plugin-transform-reserved-words": "^7.27.1",
- "@babel/plugin-transform-shorthand-properties": "^7.27.1",
- "@babel/plugin-transform-spread": "^7.28.6",
- "@babel/plugin-transform-sticky-regex": "^7.27.1",
- "@babel/plugin-transform-template-literals": "^7.27.1",
- "@babel/plugin-transform-typeof-symbol": "^7.27.1",
- "@babel/plugin-transform-unicode-escapes": "^7.27.1",
- "@babel/plugin-transform-unicode-property-regex": "^7.28.6",
- "@babel/plugin-transform-unicode-regex": "^7.27.1",
- "@babel/plugin-transform-unicode-sets-regex": "^7.28.6",
- "@babel/preset-modules": "0.1.6-no-external-plugins",
- "babel-plugin-polyfill-corejs2": "^0.4.15",
- "babel-plugin-polyfill-corejs3": "^0.14.0",
- "babel-plugin-polyfill-regenerator": "^0.6.6",
- "core-js-compat": "^3.48.0",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/preset-modules": {
- "version": "0.1.6-no-external-plugins",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
- "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/types": "^7.4.4",
- "esutils": "^2.0.2"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
- "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
- "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
- "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
- "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@borewit/text-codec": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz",
- "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/@cacheable/memory": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.8.tgz",
- "integrity": "sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw==",
- "license": "MIT",
- "dependencies": {
- "@cacheable/utils": "^2.4.0",
- "@keyv/bigmap": "^1.3.1",
- "hookified": "^1.15.1",
- "keyv": "^5.6.0"
- }
- },
- "node_modules/@cacheable/node-cache": {
- "version": "1.7.6",
- "resolved": "https://registry.npmjs.org/@cacheable/node-cache/-/node-cache-1.7.6.tgz",
- "integrity": "sha512-6Omk2SgNnjtxB5f/E6bTIWIt5xhdpx39fGNRQgU9lojvRxU68v+qY+SXXLsp3ZGukqoPjsK21wZ6XABFr/Ge3A==",
- "license": "MIT",
- "dependencies": {
- "cacheable": "^2.3.1",
- "hookified": "^1.14.0",
- "keyv": "^5.5.5"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@cacheable/utils": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.4.1.tgz",
- "integrity": "sha512-eiFgzCbIneyMlLOmNG4g9xzF7Hv3Mga4LjxjcSC/ues6VYq2+gUbQI8JqNuw/ZM8tJIeIaBGpswAsqV2V7ApgA==",
- "license": "MIT",
- "dependencies": {
- "hashery": "^1.5.1",
- "keyv": "^5.6.0"
- }
- },
- "node_modules/@drizzle-team/brocli": {
- "version": "0.10.2",
- "resolved": "https://registry.npmjs.org/@drizzle-team/brocli/-/brocli-0.10.2.tgz",
- "integrity": "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==",
- "dev": true,
- "license": "Apache-2.0"
- },
- "node_modules/@emnapi/runtime": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
- "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@esbuild-kit/core-utils": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz",
- "integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==",
- "deprecated": "Merged into tsx: https://tsx.is",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "~0.18.20",
- "source-map-support": "^0.5.21"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
- }
- },
- "node_modules/@esbuild-kit/esm-loader": {
- "version": "2.6.5",
- "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz",
- "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==",
- "deprecated": "Merged into tsx: https://tsx.is",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@esbuild-kit/core-utils": "^3.3.2",
- "get-tsconfig": "^4.7.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
- "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz",
- "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz",
- "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz",
- "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz",
- "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz",
- "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz",
- "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz",
- "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz",
- "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz",
- "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz",
- "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz",
- "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz",
- "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz",
- "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz",
- "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz",
- "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz",
- "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz",
- "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz",
- "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
- "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz",
- "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz",
- "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz",
- "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz",
- "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@floating-ui/core": {
- "version": "1.7.5",
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
- "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/utils": "^0.2.11"
- }
- },
- "node_modules/@floating-ui/dom": {
- "version": "1.7.6",
- "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
- "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/core": "^1.7.5",
- "@floating-ui/utils": "^0.2.11"
- }
- },
- "node_modules/@floating-ui/react-dom": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
- "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/dom": "^1.7.6"
- },
- "peerDependencies": {
- "react": ">=16.8.0",
- "react-dom": ">=16.8.0"
- }
- },
- "node_modules/@floating-ui/utils": {
- "version": "0.2.11",
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
- "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
- "license": "MIT"
- },
- "node_modules/@hapi/boom": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.1.tgz",
- "integrity": "sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@hapi/hoek": "^11.0.2"
- }
- },
- "node_modules/@hapi/hoek": {
- "version": "11.0.7",
- "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz",
- "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@img/colour": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
- "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@img/sharp-darwin-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
- "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-darwin-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
- "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
- "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
- "cpu": [
- "arm64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "darwin"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
- "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
- "cpu": [
- "x64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "darwin"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
- "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
- "cpu": [
- "arm"
- ],
- "libc": [
- "glibc"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
- "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-ppc64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
- "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
- "cpu": [
- "ppc64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-riscv64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
- "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
- "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
- "cpu": [
- "s390x"
- ],
- "libc": [
- "glibc"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
- "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
- "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
- "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-linux-arm": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
- "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
- "cpu": [
- "arm"
- ],
- "libc": [
- "glibc"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
- "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-ppc64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
- "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
- "cpu": [
- "ppc64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-ppc64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-riscv64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
- "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-riscv64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-s390x": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
- "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
- "cpu": [
- "s390x"
- ],
- "libc": [
- "glibc"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
- "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
- "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
- "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-wasm32": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
- "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
- "cpu": [
- "wasm32"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "@emnapi/runtime": "^1.7.0"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
- "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-ia32": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
- "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
- "cpu": [
- "ia32"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
- "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "peer": true,
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@isaacs/cliui": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
- "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
- "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/source-map": {
- "version": "0.3.11",
- "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
- "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@keyv/bigmap": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz",
- "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==",
- "license": "MIT",
- "dependencies": {
- "hashery": "^1.4.0",
- "hookified": "^1.15.0"
- },
- "engines": {
- "node": ">= 18"
- },
- "peerDependencies": {
- "keyv": "^5.6.0"
- }
- },
- "node_modules/@keyv/serialize": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz",
- "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==",
- "license": "MIT"
- },
- "node_modules/@noble/ciphers": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
- "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
- "license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
- "license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@paralleldrive/cuid2": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
- "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@noble/hashes": "^1.1.5"
- }
- },
- "node_modules/@petamoriken/float16": {
- "version": "3.9.3",
- "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.3.tgz",
- "integrity": "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@pinojs/redact": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
- "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
- "license": "MIT"
- },
- "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"
- },
- "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"
- },
- "node_modules/@protobufjs/codegen": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
- "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/fetch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
- "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.1",
- "@protobufjs/inquire": "^1.1.0"
- }
- },
- "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"
- },
- "node_modules/@protobufjs/inquire": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
- "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
- "license": "BSD-3-Clause"
- },
- "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"
- },
- "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"
- },
- "node_modules/@protobufjs/utf8": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
- "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@radix-ui/number": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
- "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
- "license": "MIT"
- },
- "node_modules/@radix-ui/primitive": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
- "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
- "license": "MIT"
- },
- "node_modules/@radix-ui/react-alert-dialog": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz",
- "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dialog": "1.1.15",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-arrow": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
- "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-checkbox": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
- "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-previous": "1.1.1",
- "@radix-ui/react-use-size": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-collection": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
- "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-compose-refs": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
- "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-context": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
- "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dialog": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
- "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-direction": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
- "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
- "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-escape-keydown": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dropdown-menu": {
- "version": "2.1.16",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
- "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-menu": "2.1.16",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
- "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-focus-scope": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
- "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-id": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
- "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-label": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz",
- "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
- "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-slot": "1.2.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-menu": {
- "version": "2.1.16",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
- "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-popper": "1.2.8",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-roving-focus": "1.1.11",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-popover": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
- "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-popper": "1.2.8",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-popper": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
- "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/react-dom": "^2.0.0",
- "@radix-ui/react-arrow": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-layout-effect": "1.1.1",
- "@radix-ui/react-use-rect": "1.1.1",
- "@radix-ui/react-use-size": "1.1.1",
- "@radix-ui/rect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-portal": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
- "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-presence": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
- "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-primitive": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
- "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-slot": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-progress": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz",
- "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-context": "1.1.3",
- "@radix-ui/react-primitive": "2.1.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
- "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
- "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-slot": "1.2.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-radio-group": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz",
- "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-roving-focus": "1.1.11",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-previous": "1.1.1",
- "@radix-ui/react-use-size": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-roving-focus": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
- "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-controllable-state": "1.2.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-select": {
- "version": "2.2.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
- "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/number": "1.1.1",
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-popper": "1.2.8",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-layout-effect": "1.1.1",
- "@radix-ui/react-use-previous": "1.1.1",
- "@radix-ui/react-visually-hidden": "1.2.3",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-separator": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
- "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
- "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-slot": "1.2.4"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-slot": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
- "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-switch": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
- "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-previous": "1.1.1",
- "@radix-ui/react-use-size": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-tabs": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
- "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-roving-focus": "1.1.11",
- "@radix-ui/react-use-controllable-state": "1.2.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-toast": {
- "version": "1.2.15",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz",
- "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-use-layout-effect": "1.1.1",
- "@radix-ui/react-visually-hidden": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-tooltip": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
- "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-popper": "1.2.8",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "@radix-ui/react-visually-hidden": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-callback-ref": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
- "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-controllable-state": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
- "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-effect-event": "0.0.2",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-effect-event": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
- "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-escape-keydown": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
- "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-callback-ref": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-layout-effect": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
- "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-previous": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
- "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-rect": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
- "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/rect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-size": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
- "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-visually-hidden": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
- "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/rect": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
- "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
- "license": "MIT"
- },
- "node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-beta.27",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
- "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@rollup/plugin-node-resolve": {
- "version": "15.3.1",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
- "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==",
- "license": "MIT",
- "dependencies": {
- "@rollup/pluginutils": "^5.0.1",
- "@types/resolve": "1.20.2",
- "deepmerge": "^4.2.2",
- "is-module": "^1.0.0",
- "resolve": "^1.22.1"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^2.78.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
- }
- },
- "node_modules/@rollup/plugin-terser": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
- "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
- "license": "MIT",
- "dependencies": {
- "serialize-javascript": "^6.0.1",
- "smob": "^1.0.0",
- "terser": "^5.17.4"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^2.0.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
- }
- },
- "node_modules/@rollup/pluginutils": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
- "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==",
- "license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.0",
- "estree-walker": "^2.0.2",
- "picomatch": "^4.0.2"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
- }
- },
- "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
- "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
- "license": "MIT"
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz",
- "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz",
- "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz",
- "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz",
- "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz",
- "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz",
- "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz",
- "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==",
- "cpu": [
- "arm"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz",
- "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==",
- "cpu": [
- "arm"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz",
- "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz",
- "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz",
- "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==",
- "cpu": [
- "loong64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz",
- "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==",
- "cpu": [
- "loong64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz",
- "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==",
- "cpu": [
- "ppc64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz",
- "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==",
- "cpu": [
- "ppc64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz",
- "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz",
- "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz",
- "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==",
- "cpu": [
- "s390x"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz",
- "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz",
- "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz",
- "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ]
- },
- "node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz",
- "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz",
- "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz",
- "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz",
- "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz",
- "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@socket.io/component-emitter": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
- "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
- "license": "MIT"
- },
- "node_modules/@stripe/stripe-js": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-9.3.1.tgz",
- "integrity": "sha512-oWpAEENuVg8aw4W2OUAM9WxRDtIV2YTLr2nr6qHT+D8tHPW7bya61ufinPpUespyRNUVXqesnHo+jQdUNsGywA==",
- "license": "MIT",
- "engines": {
- "node": ">=12.16"
- }
- },
- "node_modules/@surma/rollup-plugin-off-main-thread": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
- "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "ejs": "^3.1.6",
- "json5": "^2.2.0",
- "magic-string": "^0.25.0",
- "string.prototype.matchall": "^4.0.6"
- }
- },
- "node_modules/@surma/rollup-plugin-off-main-thread/node_modules/magic-string": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
- "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
- "license": "MIT",
- "dependencies": {
- "sourcemap-codec": "^1.4.8"
- }
- },
- "node_modules/@swc/helpers": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.21.tgz",
- "integrity": "sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.4.tgz",
- "integrity": "sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "^5.19.0",
- "jiti": "^2.6.1",
- "lightningcss": "1.32.0",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.2.4"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.4.tgz",
- "integrity": "sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.2.4",
- "@tailwindcss/oxide-darwin-arm64": "4.2.4",
- "@tailwindcss/oxide-darwin-x64": "4.2.4",
- "@tailwindcss/oxide-freebsd-x64": "4.2.4",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.4",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.2.4",
- "@tailwindcss/oxide-linux-arm64-musl": "4.2.4",
- "@tailwindcss/oxide-linux-x64-gnu": "4.2.4",
- "@tailwindcss/oxide-linux-x64-musl": "4.2.4",
- "@tailwindcss/oxide-wasm32-wasi": "4.2.4",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.2.4",
- "@tailwindcss/oxide-win32-x64-msvc": "4.2.4"
- }
- },
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.4.tgz",
- "integrity": "sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.4.tgz",
- "integrity": "sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.4.tgz",
- "integrity": "sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.4.tgz",
- "integrity": "sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.4.tgz",
- "integrity": "sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.4.tgz",
- "integrity": "sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.4.tgz",
- "integrity": "sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.4.tgz",
- "integrity": "sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.4.tgz",
- "integrity": "sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.4.tgz",
- "integrity": "sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.8.1",
- "@emnapi/runtime": "^1.8.1",
- "@emnapi/wasi-threads": "^1.1.0",
- "@napi-rs/wasm-runtime": "^1.1.1",
- "@tybys/wasm-util": "^0.10.1",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.4.tgz",
- "integrity": "sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.4.tgz",
- "integrity": "sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.4.tgz",
- "integrity": "sha512-pCvohwOCspk3ZFn6eJzrrX3g4n2JY73H6MmYC87XfGPyTty4YsCjYTMArRZm/zOI8dIt3+EcrLHAFPe5A4bgtw==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.2.4",
- "@tailwindcss/oxide": "4.2.4",
- "tailwindcss": "4.2.4"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/@tanstack/query-core": {
- "version": "5.100.1",
- "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.1.tgz",
- "integrity": "sha512-awvQhOO/2TrSCHE5LKKsXcvvj6WSBncwEcMFCB/ez0Qs0b17iyyivoGArNV3HFfXryZwCpnb/olsaBBKrIbtSw==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/tannerlinsley"
- }
- },
- "node_modules/@tanstack/react-query": {
- "version": "5.100.1",
- "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.100.1.tgz",
- "integrity": "sha512-UgWRLhQKprC37SsO6y1zRabOqDmM2gsdTNPbqTT35yl7kOOhwXU4nyfOiGHXPwoEFJV1IpSk85hjIFjNFWVpzw==",
- "license": "MIT",
- "dependencies": {
- "@tanstack/query-core": "5.100.1"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/tannerlinsley"
- },
- "peerDependencies": {
- "react": "^18 || ^19"
- }
- },
- "node_modules/@tokenizer/inflate": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
- "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.3",
- "token-types": "^6.1.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/@tokenizer/token": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
- "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
- "license": "MIT"
- },
- "node_modules/@trpc/client": {
- "version": "11.0.0-rc.660",
- "resolved": "https://registry.npmjs.org/@trpc/client/-/client-11.0.0-rc.660.tgz",
- "integrity": "sha512-bNpkZEfyMGKHynYFxdLpY8nJ1n7E3JHKcd4Pe2cagmpkzOEF9tFT3kzNf+eLI8XMG8196lTRR0J0W2/1Q8/cug==",
- "funding": [
- "https://trpc.io/sponsor"
- ],
- "license": "MIT",
- "peerDependencies": {
- "@trpc/server": "11.0.0-rc.660+74625d5e4",
- "typescript": ">=5.6.2"
- }
- },
- "node_modules/@trpc/react-query": {
- "version": "11.0.0-rc.660",
- "resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-11.0.0-rc.660.tgz",
- "integrity": "sha512-U2BHtYVt+8jt0a8Nrrk5cep8O1UZRxtTCBHtXie9kmJyQWWml43KfHxL5ssnFywaFrDZQz6Ec7kIoOxR/CQNfg==",
- "funding": [
- "https://trpc.io/sponsor"
- ],
- "license": "MIT",
- "peerDependencies": {
- "@tanstack/react-query": "^5.59.15",
- "@trpc/client": "11.0.0-rc.660+74625d5e4",
- "@trpc/server": "11.0.0-rc.660+74625d5e4",
- "react": ">=18.2.0",
- "react-dom": ">=18.2.0",
- "typescript": ">=5.6.2"
- }
- },
- "node_modules/@trpc/server": {
- "version": "11.0.0-rc.660",
- "resolved": "https://registry.npmjs.org/@trpc/server/-/server-11.0.0-rc.660.tgz",
- "integrity": "sha512-QUapcZCNOpHT7ng9LceGc9ImkboWd0Go9ryrduZpL+p4jdfaC6409AQ3x4XEW6Wu3yBmZAn4CywCsDrDhjDy/w==",
- "funding": [
- "https://trpc.io/sponsor"
- ],
- "license": "MIT",
- "peerDependencies": {
- "typescript": ">=5.6.2"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
- "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.28.2"
- }
- },
- "node_modules/@types/bcryptjs": {
- "version": "2.4.6",
- "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz",
- "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/body-parser": {
- "version": "1.19.6",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
- "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/connect": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/connect": {
- "version": "3.4.38",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
- "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/cookie-parser": {
- "version": "1.4.10",
- "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz",
- "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/express": "*"
- }
- },
- "node_modules/@types/cookiejar": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz",
- "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/cors": {
- "version": "2.8.19",
- "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
- "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/d3-array": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
- "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-color": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
- "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
- "license": "MIT"
- },
- "node_modules/@types/d3-ease": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
- "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
- "license": "MIT"
- },
- "node_modules/@types/d3-interpolate": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
- "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-color": "*"
- }
- },
- "node_modules/@types/d3-path": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
- "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-scale": {
- "version": "4.0.9",
- "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
- "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-time": "*"
- }
- },
- "node_modules/@types/d3-shape": {
- "version": "3.1.8",
- "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz",
- "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-path": "*"
- }
- },
- "node_modules/@types/d3-time": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
- "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
- "license": "MIT"
- },
- "node_modules/@types/d3-timer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
- "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
- "license": "MIT"
- },
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "license": "MIT"
- },
- "node_modules/@types/express": {
- "version": "4.17.25",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
- "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.33",
- "@types/qs": "*",
- "@types/serve-static": "^1"
- }
- },
- "node_modules/@types/express-serve-static-core": {
- "version": "4.19.8",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
- "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "@types/qs": "*",
- "@types/range-parser": "*",
- "@types/send": "*"
- }
- },
- "node_modules/@types/http-errors": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
- "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
- "dev": true,
- "license": "MIT"
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/ms": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/long": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
- "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==",
- "license": "MIT"
- },
- "node_modules/@types/methods": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz",
- "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/mime": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
- "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/ms": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
- "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/node": {
- "version": "22.19.17",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz",
- "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==",
- "license": "MIT",
- "dependencies": {
- "undici-types": "~6.21.0"
- }
- },
- "node_modules/@types/nodemailer": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-8.0.0.tgz",
- "integrity": "sha512-fyf8jWULsCo0d0BuoQ75i6IeoHs47qcqxWc7yUdUcV0pOZGjUTTOvwdG1PRXUDqN/8A64yQdQdnA2pZgcdi+cA==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/pdfkit": {
- "version": "0.17.6",
- "resolved": "https://registry.npmjs.org/@types/pdfkit/-/pdfkit-0.17.6.tgz",
- "integrity": "sha512-tIwzxk2uWKp0Cq9JIluQXJid77lYhF52EsIOwhsMF4iWLA6YneoBR1xVKYYdAysHuepUB0OX4tdwMiUDdGKmig==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/qrcode": {
- "version": "1.5.6",
- "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.6.tgz",
- "integrity": "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/qs": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz",
- "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/range-parser": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
- "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/react": {
- "version": "19.2.14",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
- "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "csstype": "^3.2.2"
- }
- },
- "node_modules/@types/react-dom": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
- "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
- "devOptional": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^19.2.0"
- }
- },
- "node_modules/@types/resolve": {
- "version": "1.20.2",
- "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
- "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
- "license": "MIT"
- },
- "node_modules/@types/send": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
- "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/serve-static": {
- "version": "1.15.10",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
- "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/http-errors": "*",
- "@types/node": "*",
- "@types/send": "<1"
- }
- },
- "node_modules/@types/serve-static/node_modules/@types/send": {
- "version": "0.17.6",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
- "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/mime": "^1",
- "@types/node": "*"
- }
- },
- "node_modules/@types/superagent": {
- "version": "8.1.9",
- "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz",
- "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/cookiejar": "^2.1.5",
- "@types/methods": "^1.1.4",
- "@types/node": "*",
- "form-data": "^4.0.0"
- }
- },
- "node_modules/@types/supertest": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-7.2.0.tgz",
- "integrity": "sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/methods": "^1.1.4",
- "@types/superagent": "^8.1.0"
- }
- },
- "node_modules/@types/trusted-types": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "license": "MIT"
- },
- "node_modules/@types/ws": {
- "version": "8.18.1",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
- "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@vitejs/plugin-react": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
- "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.28.0",
- "@babel/plugin-transform-react-jsx-self": "^7.27.1",
- "@babel/plugin-transform-react-jsx-source": "^7.27.1",
- "@rolldown/pluginutils": "1.0.0-beta.27",
- "@types/babel__core": "^7.20.5",
- "react-refresh": "^0.17.0"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "peerDependencies": {
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
- }
- },
- "node_modules/@vitest/expect": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz",
- "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/spy": "2.1.9",
- "@vitest/utils": "2.1.9",
- "chai": "^5.1.2",
- "tinyrainbow": "^1.2.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/pretty-format": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz",
- "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tinyrainbow": "^1.2.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/runner": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz",
- "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/utils": "2.1.9",
- "pathe": "^1.1.2"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/snapshot": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz",
- "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "2.1.9",
- "magic-string": "^0.30.12",
- "pathe": "^1.1.2"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/spy": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz",
- "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tinyspy": "^3.0.2"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/utils": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz",
- "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "2.1.9",
- "loupe": "^3.1.2",
- "tinyrainbow": "^1.2.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@whiskeysockets/baileys": {
- "version": "7.0.0-rc.9",
- "resolved": "https://registry.npmjs.org/@whiskeysockets/baileys/-/baileys-7.0.0-rc.9.tgz",
- "integrity": "sha512-YFm5gKXfDP9byCXCW3OPHKXLzrAKzolzgVUlRosHHgwbnf2YOO3XknkMm6J7+F0ns8OA0uuSBhgkRHTDtqkacw==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "@cacheable/node-cache": "^1.4.0",
- "@hapi/boom": "^9.1.3",
- "async-mutex": "^0.5.0",
- "libsignal": "git+https://github.com/whiskeysockets/libsignal-node.git",
- "lru-cache": "^11.1.0",
- "music-metadata": "^11.7.0",
- "p-queue": "^9.0.0",
- "pino": "^9.6",
- "protobufjs": "^7.2.4",
- "ws": "^8.13.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "audio-decode": "^2.1.3",
- "jimp": "^1.6.0",
- "link-preview-js": "^3.0.0",
- "sharp": "*"
- },
- "peerDependenciesMeta": {
- "audio-decode": {
- "optional": true
- },
- "jimp": {
- "optional": true
- },
- "link-preview-js": {
- "optional": true
- }
- }
- },
- "node_modules/@whiskeysockets/baileys/node_modules/@hapi/boom": {
- "version": "9.1.4",
- "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-9.1.4.tgz",
- "integrity": "sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@hapi/hoek": "9.x.x"
- }
- },
- "node_modules/@whiskeysockets/baileys/node_modules/@hapi/hoek": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
- "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@whiskeysockets/baileys/node_modules/lru-cache": {
- "version": "11.3.5",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
- "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/@whiskeysockets/baileys/node_modules/pino": {
- "version": "9.14.0",
- "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz",
- "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==",
- "license": "MIT",
- "dependencies": {
- "@pinojs/redact": "^0.4.0",
- "atomic-sleep": "^1.0.0",
- "on-exit-leak-free": "^2.1.0",
- "pino-abstract-transport": "^2.0.0",
- "pino-std-serializers": "^7.0.0",
- "process-warning": "^5.0.0",
- "quick-format-unescaped": "^4.0.3",
- "real-require": "^0.2.0",
- "safe-stable-stringify": "^2.3.1",
- "sonic-boom": "^4.0.1",
- "thread-stream": "^3.0.0"
- },
- "bin": {
- "pino": "bin.js"
- }
- },
- "node_modules/@whiskeysockets/baileys/node_modules/pino-abstract-transport": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
- "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
- "license": "MIT",
- "dependencies": {
- "split2": "^4.0.0"
- }
- },
- "node_modules/@whiskeysockets/baileys/node_modules/thread-stream": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz",
- "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==",
- "license": "MIT",
- "dependencies": {
- "real-require": "^0.2.0"
- }
- },
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/acorn": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
- "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
- "license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "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",
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/ajv": {
- "version": "8.20.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
- "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/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/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/aria-hidden": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
- "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
- "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "is-array-buffer": "^3.0.5"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "license": "MIT"
- },
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
- "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
- "license": "MIT",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.1",
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "is-array-buffer": "^3.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/asap": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/assertion-error": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
- "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/async": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
- "license": "MIT"
- },
- "node_modules/async-function": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
- "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/async-mutex": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz",
- "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "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"
- },
- "node_modules/at-least-node": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
- "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
- "license": "ISC",
- "engines": {
- "node": ">= 4.0.0"
- }
- },
- "node_modules/atomic-sleep": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
- "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
- "license": "MIT",
- "dependencies": {
- "possible-typed-array-names": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/aws-ssl-profiles": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
- "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
- "license": "MIT",
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/axios": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
- "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.11",
- "form-data": "^4.0.5",
- "proxy-from-env": "^2.1.0"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.4.17",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz",
- "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==",
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-define-polyfill-provider": "^0.6.8",
- "semver": "^6.3.1"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.14.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz",
- "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.8",
- "core-js-compat": "^3.48.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz",
- "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.8"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "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/base64id": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
- "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
- "license": "MIT",
- "engines": {
- "node": "^4.5.0 || >= 5.9"
- }
- },
- "node_modules/baseline-browser-mapping": {
- "version": "2.10.21",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.21.tgz",
- "integrity": "sha512-Q+rUQ7Uz8AHM7DEaNdwvfFCTq7a43lNTzuS94eiWqwyxfV/wJv+oUivef51T91mmRY4d4A1u9rcSvkeufCVXlA==",
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.cjs"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/bcryptjs": {
- "version": "2.4.3",
- "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
- "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
- "license": "MIT"
- },
- "node_modules/body-parser": {
- "version": "1.20.5",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
- "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "~1.2.0",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "on-finished": "~2.4.1",
- "qs": "~6.15.1",
- "raw-body": "~2.5.3",
- "type-is": "~1.6.18",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/body-parser/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/body-parser/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/body-parser/node_modules/qs": {
- "version": "6.15.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
- "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/brace-expansion": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
- "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/brotli": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
- "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.1.2"
- }
- },
- "node_modules/browserify-zlib": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
- "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
- "license": "MIT",
- "dependencies": {
- "pako": "~1.0.5"
- }
- },
- "node_modules/browserslist": {
- "version": "4.28.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
- "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "baseline-browser-mapping": "^2.10.12",
- "caniuse-lite": "^1.0.30001782",
- "electron-to-chromium": "^1.5.328",
- "node-releases": "^2.0.36",
- "update-browserslist-db": "^1.2.3"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "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/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "license": "MIT"
- },
- "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/cac": {
- "version": "6.7.14",
- "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cacheable": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.4.tgz",
- "integrity": "sha512-djgxybDbw9fL/ZWMI3+CE8ZilNxcwFkVtDc1gJ+IlOSSWkSMPQabhV/XCHTQ6pwwN6aivXPZ43omTooZiX06Ew==",
- "license": "MIT",
- "dependencies": {
- "@cacheable/memory": "^2.0.8",
- "@cacheable/utils": "^2.4.0",
- "hookified": "^1.15.0",
- "keyv": "^5.6.0",
- "qified": "^0.9.0"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
- "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "get-intrinsic": "^1.3.0",
- "set-function-length": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "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/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001790",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz",
- "integrity": "sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/chai": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
- "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assertion-error": "^2.0.1",
- "check-error": "^2.1.1",
- "deep-eql": "^5.0.1",
- "loupe": "^3.1.0",
- "pathval": "^2.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/chalk/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/check-error": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
- "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 16"
- }
- },
- "node_modules/class-variance-authority": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
- "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
- "license": "Apache-2.0",
- "dependencies": {
- "clsx": "^2.1.1"
- },
- "funding": {
- "url": "https://polar.sh/cva"
- }
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/clone": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
- "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
- "license": "MIT",
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/clsx": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
- "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cmdk": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz",
- "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "^1.1.1",
- "@radix-ui/react-dialog": "^1.1.6",
- "@radix-ui/react-id": "^1.1.0",
- "@radix-ui/react-primitive": "^2.0.2"
- },
- "peerDependencies": {
- "react": "^18 || ^19 || ^19.0.0-rc",
- "react-dom": "^18 || ^19 || ^19.0.0-rc"
- }
- },
- "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/colorette": {
- "version": "2.0.20",
- "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
- "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
- "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",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "license": "MIT"
- },
- "node_modules/common-tags": {
- "version": "1.8.2",
- "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
- "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/component-emitter": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
- "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/concurrently": {
- "version": "9.2.1",
- "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
- "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "4.1.2",
- "rxjs": "7.8.2",
- "shell-quote": "1.8.3",
- "supports-color": "8.1.1",
- "tree-kill": "1.2.2",
- "yargs": "17.7.2"
- },
- "bin": {
- "conc": "dist/bin/concurrently.js",
- "concurrently": "dist/bin/concurrently.js"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
- }
- },
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "license": "MIT"
- },
- "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-parser": {
- "version": "1.4.7",
- "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
- "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
- "license": "MIT",
- "dependencies": {
- "cookie": "0.7.2",
- "cookie-signature": "1.0.6"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "license": "MIT"
- },
- "node_modules/cookiejar": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
- "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/core-js-compat": {
- "version": "3.49.0",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz",
- "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==",
- "license": "MIT",
- "dependencies": {
- "browserslist": "^4.28.1"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/core-js"
- }
- },
- "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/cross-spawn/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/cross-spawn/node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/crypto-random-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
- "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/csstype": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
- "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "license": "MIT"
- },
- "node_modules/curve25519-js": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/curve25519-js/-/curve25519-js-0.0.4.tgz",
- "integrity": "sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==",
- "license": "MIT"
- },
- "node_modules/d3-array": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
- "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
- "license": "ISC",
- "dependencies": {
- "internmap": "1 - 2"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-color": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
- "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-ease": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
- "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-format": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
- "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-interpolate": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
- "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-path": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
- "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
- "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2.10.0 - 3",
- "d3-format": "1 - 3",
- "d3-interpolate": "1.2.0 - 3",
- "d3-time": "2.1.1 - 3",
- "d3-time-format": "2 - 4"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-shape": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
- "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
- "license": "ISC",
- "dependencies": {
- "d3-path": "^3.1.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
- "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time-format": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
- "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
- "license": "ISC",
- "dependencies": {
- "d3-time": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-timer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
- "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/data-view-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
- "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/data-view-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
- "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/inspect-js"
- }
- },
- "node_modules/data-view-byte-offset": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
- "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/date-fns": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
- "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/kossnocorp"
- }
- },
- "node_modules/dateformat": {
- "version": "4.6.3",
- "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
- "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/dayjs": {
- "version": "1.11.20",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz",
- "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==",
- "license": "MIT"
- },
- "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/decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/decimal.js-light": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
- "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
- "license": "MIT"
- },
- "node_modules/deep-eql": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
- "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/denque": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
- "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=0.10"
- }
- },
- "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/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/detect-node-es": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
- "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
- "license": "MIT"
- },
- "node_modules/dezalgo": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
- "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "asap": "^2.0.0",
- "wrappy": "1"
- }
- },
- "node_modules/dfa": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
- "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
- "license": "MIT"
- },
- "node_modules/dijkstrajs": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
- "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
- "license": "MIT"
- },
- "node_modules/dom-helpers": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
- "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.8.7",
- "csstype": "^3.0.2"
- }
- },
- "node_modules/drizzle-kit": {
- "version": "0.30.6",
- "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.30.6.tgz",
- "integrity": "sha512-U4wWit0fyZuGuP7iNmRleQyK2V8wCuv57vf5l3MnG4z4fzNTjY/U13M8owyQ5RavqvqxBifWORaR3wIUzlN64g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@drizzle-team/brocli": "^0.10.2",
- "@esbuild-kit/esm-loader": "^2.5.5",
- "esbuild": "^0.19.7",
- "esbuild-register": "^3.5.0",
- "gel": "^2.0.0"
- },
- "bin": {
- "drizzle-kit": "bin.cjs"
- }
- },
- "node_modules/drizzle-orm": {
- "version": "0.38.4",
- "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.38.4.tgz",
- "integrity": "sha512-s7/5BpLKO+WJRHspvpqTydxFob8i1vo2rEx4pY6TGY7QSMuUfWUuzaY0DIpXCkgHOo37BaFC+SJQb99dDUXT3Q==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@aws-sdk/client-rds-data": ">=3",
- "@cloudflare/workers-types": ">=4",
- "@electric-sql/pglite": ">=0.2.0",
- "@libsql/client": ">=0.10.0",
- "@libsql/client-wasm": ">=0.10.0",
- "@neondatabase/serverless": ">=0.10.0",
- "@op-engineering/op-sqlite": ">=2",
- "@opentelemetry/api": "^1.4.1",
- "@planetscale/database": ">=1",
- "@prisma/client": "*",
- "@tidbcloud/serverless": "*",
- "@types/better-sqlite3": "*",
- "@types/pg": "*",
- "@types/react": ">=18",
- "@types/sql.js": "*",
- "@vercel/postgres": ">=0.8.0",
- "@xata.io/client": "*",
- "better-sqlite3": ">=7",
- "bun-types": "*",
- "expo-sqlite": ">=14.0.0",
- "knex": "*",
- "kysely": "*",
- "mysql2": ">=2",
- "pg": ">=8",
- "postgres": ">=3",
- "react": ">=18",
- "sql.js": ">=1",
- "sqlite3": ">=5"
- },
- "peerDependenciesMeta": {
- "@aws-sdk/client-rds-data": {
- "optional": true
- },
- "@cloudflare/workers-types": {
- "optional": true
- },
- "@electric-sql/pglite": {
- "optional": true
- },
- "@libsql/client": {
- "optional": true
- },
- "@libsql/client-wasm": {
- "optional": true
- },
- "@neondatabase/serverless": {
- "optional": true
- },
- "@op-engineering/op-sqlite": {
- "optional": true
- },
- "@opentelemetry/api": {
- "optional": true
- },
- "@planetscale/database": {
- "optional": true
- },
- "@prisma/client": {
- "optional": true
- },
- "@tidbcloud/serverless": {
- "optional": true
- },
- "@types/better-sqlite3": {
- "optional": true
- },
- "@types/pg": {
- "optional": true
- },
- "@types/react": {
- "optional": true
- },
- "@types/sql.js": {
- "optional": true
- },
- "@vercel/postgres": {
- "optional": true
- },
- "@xata.io/client": {
- "optional": true
- },
- "better-sqlite3": {
- "optional": true
- },
- "bun-types": {
- "optional": true
- },
- "expo-sqlite": {
- "optional": true
- },
- "knex": {
- "optional": true
- },
- "kysely": {
- "optional": true
- },
- "mysql2": {
- "optional": true
- },
- "pg": {
- "optional": true
- },
- "postgres": {
- "optional": true
- },
- "prisma": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "sql.js": {
- "optional": true
- },
- "sqlite3": {
- "optional": true
- }
- }
- },
- "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/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/ejs": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
- "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
- "license": "Apache-2.0",
- "dependencies": {
- "jake": "^10.8.5"
- },
- "bin": {
- "ejs": "bin/cli.js"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.344",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz",
- "integrity": "sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==",
- "license": "ISC"
- },
- "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/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",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/engine.io": {
- "version": "6.6.6",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.6.tgz",
- "integrity": "sha512-U2SN0w3OpjFRVlrc17E6TMDmH58Xl9rai1MblNjAdwWp07Kk+llmzX0hjDpQdrDGzwmvOtgM5yI+meYX6iZ2xA==",
- "license": "MIT",
- "dependencies": {
- "@types/cors": "^2.8.12",
- "@types/node": ">=10.0.0",
- "@types/ws": "^8.5.12",
- "accepts": "~1.3.4",
- "base64id": "2.0.0",
- "cookie": "~0.7.2",
- "cors": "~2.8.5",
- "debug": "~4.4.1",
- "engine.io-parser": "~5.2.1",
- "ws": "~8.18.3"
- },
- "engines": {
- "node": ">=10.2.0"
- }
- },
- "node_modules/engine.io-client": {
- "version": "6.6.4",
- "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz",
- "integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==",
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.4.1",
- "engine.io-parser": "~5.2.1",
- "ws": "~8.18.3",
- "xmlhttprequest-ssl": "~2.1.1"
- }
- },
- "node_modules/engine.io-parser": {
- "version": "5.2.3",
- "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
- "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/enhanced-resolve": {
- "version": "5.21.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
- "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/env-paths": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz",
- "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/es-abstract": {
- "version": "1.24.2",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz",
- "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==",
- "license": "MIT",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.2",
- "arraybuffer.prototype.slice": "^1.0.4",
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "data-view-buffer": "^1.0.2",
- "data-view-byte-length": "^1.0.2",
- "data-view-byte-offset": "^1.0.1",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "es-set-tostringtag": "^2.1.0",
- "es-to-primitive": "^1.3.0",
- "function.prototype.name": "^1.1.8",
- "get-intrinsic": "^1.3.0",
- "get-proto": "^1.0.1",
- "get-symbol-description": "^1.1.0",
- "globalthis": "^1.0.4",
- "gopd": "^1.2.0",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "internal-slot": "^1.1.0",
- "is-array-buffer": "^3.0.5",
- "is-callable": "^1.2.7",
- "is-data-view": "^1.0.2",
- "is-negative-zero": "^2.0.3",
- "is-regex": "^1.2.1",
- "is-set": "^2.0.3",
- "is-shared-array-buffer": "^1.0.4",
- "is-string": "^1.1.1",
- "is-typed-array": "^1.1.15",
- "is-weakref": "^1.1.1",
- "math-intrinsics": "^1.1.0",
- "object-inspect": "^1.13.4",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.7",
- "own-keys": "^1.0.1",
- "regexp.prototype.flags": "^1.5.4",
- "safe-array-concat": "^1.1.3",
- "safe-push-apply": "^1.0.0",
- "safe-regex-test": "^1.1.0",
- "set-proto": "^1.0.0",
- "stop-iteration-iterator": "^1.1.0",
- "string.prototype.trim": "^1.2.10",
- "string.prototype.trimend": "^1.0.9",
- "string.prototype.trimstart": "^1.0.8",
- "typed-array-buffer": "^1.0.3",
- "typed-array-byte-length": "^1.0.3",
- "typed-array-byte-offset": "^1.0.4",
- "typed-array-length": "^1.0.7",
- "unbox-primitive": "^1.1.0",
- "which-typed-array": "^1.1.19"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "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-module-lexer": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
- "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "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",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-to-primitive": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
- "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
- "license": "MIT",
- "dependencies": {
- "is-callable": "^1.2.7",
- "is-date-object": "^1.0.5",
- "is-symbol": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/esbuild": {
- "version": "0.19.12",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
- "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.19.12",
- "@esbuild/android-arm": "0.19.12",
- "@esbuild/android-arm64": "0.19.12",
- "@esbuild/android-x64": "0.19.12",
- "@esbuild/darwin-arm64": "0.19.12",
- "@esbuild/darwin-x64": "0.19.12",
- "@esbuild/freebsd-arm64": "0.19.12",
- "@esbuild/freebsd-x64": "0.19.12",
- "@esbuild/linux-arm": "0.19.12",
- "@esbuild/linux-arm64": "0.19.12",
- "@esbuild/linux-ia32": "0.19.12",
- "@esbuild/linux-loong64": "0.19.12",
- "@esbuild/linux-mips64el": "0.19.12",
- "@esbuild/linux-ppc64": "0.19.12",
- "@esbuild/linux-riscv64": "0.19.12",
- "@esbuild/linux-s390x": "0.19.12",
- "@esbuild/linux-x64": "0.19.12",
- "@esbuild/netbsd-x64": "0.19.12",
- "@esbuild/openbsd-x64": "0.19.12",
- "@esbuild/sunos-x64": "0.19.12",
- "@esbuild/win32-arm64": "0.19.12",
- "@esbuild/win32-ia32": "0.19.12",
- "@esbuild/win32-x64": "0.19.12"
- }
- },
- "node_modules/esbuild-register": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz",
- "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "peerDependencies": {
- "esbuild": ">=0.12 <1"
- }
- },
- "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",
- "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/estree-walker": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
- "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/eventemitter3": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
- "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
- "license": "MIT"
- },
- "node_modules/expect-type": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
- "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/express": {
- "version": "4.22.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
- "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "~1.20.3",
- "content-disposition": "~0.5.4",
- "content-type": "~1.0.4",
- "cookie": "~0.7.1",
- "cookie-signature": "~1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.3.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.0",
- "merge-descriptors": "1.0.3",
- "methods": "~1.1.2",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "~0.1.12",
- "proxy-addr": "~2.0.7",
- "qs": "~6.14.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "~0.19.0",
- "serve-static": "~1.16.2",
- "setprototypeof": "1.2.0",
- "statuses": "~2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express-rate-limit": {
- "version": "8.4.1",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.4.1.tgz",
- "integrity": "sha512-NGVYwQSAyEQgzxX1iCM978PP9AdO/hW93gMcF6ZwQCm+rFvLsBH6w4xcXWTcliS8La5EPRN3p9wzItqBwJrfNw==",
- "license": "MIT",
- "dependencies": {
- "ip-address": "10.1.0"
- },
- "engines": {
- "node": ">= 16"
- },
- "funding": {
- "url": "https://github.com/sponsors/express-rate-limit"
- },
- "peerDependencies": {
- "express": ">= 4.11"
- }
- },
- "node_modules/express/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/express/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/fast-copy": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.3.tgz",
- "integrity": "sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==",
- "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-equals": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz",
- "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "license": "MIT"
- },
- "node_modules/fast-safe-stringify": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
- "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
- "license": "MIT"
- },
- "node_modules/fast-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
- "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/file-type": {
- "version": "21.3.4",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz",
- "integrity": "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==",
- "license": "MIT",
- "dependencies": {
- "@tokenizer/inflate": "^0.4.1",
- "strtok3": "^10.3.4",
- "token-types": "^6.1.1",
- "uint8array-extras": "^1.4.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/file-type?sponsor=1"
- }
- },
- "node_modules/filelist": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz",
- "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==",
- "license": "Apache-2.0",
- "dependencies": {
- "minimatch": "^5.0.1"
- }
- },
- "node_modules/filelist/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/filelist/node_modules/brace-expansion": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
- "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/filelist/node_modules/minimatch": {
- "version": "5.1.9",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
- "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
- "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "~2.0.2",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/finalhandler/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/finalhandler/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "license": "MIT",
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/follow-redirects": {
- "version": "1.16.0",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
- "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
- "node_modules/fontkit": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz",
- "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
- "license": "MIT",
- "dependencies": {
- "@swc/helpers": "^0.5.12",
- "brotli": "^1.3.2",
- "clone": "^2.1.2",
- "dfa": "^1.2.0",
- "fast-deep-equal": "^3.1.3",
- "restructure": "^3.0.0",
- "tiny-inflate": "^1.0.3",
- "unicode-properties": "^1.4.0",
- "unicode-trie": "^2.0.0"
- }
- },
- "node_modules/for-each": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
- "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
- "license": "MIT",
- "dependencies": {
- "is-callable": "^1.2.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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": "4.0.5",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/formidable": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
- "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@paralleldrive/cuid2": "^2.2.2",
- "dezalgo": "^1.0.4",
- "once": "^1.4.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "funding": {
- "url": "https://ko-fi.com/tunnckoCore/commissions"
- }
- },
- "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/framer-motion": {
- "version": "11.18.2",
- "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz",
- "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==",
- "license": "MIT",
- "dependencies": {
- "motion-dom": "^11.18.1",
- "motion-utils": "^11.18.1",
- "tslib": "^2.4.0"
- },
- "peerDependencies": {
- "@emotion/is-prop-valid": "*",
- "react": "^18.0.0 || ^19.0.0",
- "react-dom": "^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@emotion/is-prop-valid": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
- "license": "MIT",
- "dependencies": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/function.prototype.name": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
- "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "functions-have-names": "^1.2.3",
- "hasown": "^2.0.2",
- "is-callable": "^1.2.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gel": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/gel/-/gel-2.2.0.tgz",
- "integrity": "sha512-q0ma7z2swmoamHQusey8ayo8+ilVdzDt4WTxSPzq/yRqvucWRfymRVMvNgmSC0XK7eNjjEZEcplxpgaNojKdmQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@petamoriken/float16": "^3.8.7",
- "debug": "^4.3.4",
- "env-paths": "^3.0.0",
- "semver": "^7.6.2",
- "shell-quote": "^1.8.1",
- "which": "^4.0.0"
- },
- "bin": {
- "gel": "dist/cli.mjs"
- },
- "engines": {
- "node": ">= 18.0.0"
- }
- },
- "node_modules/gel/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/generate-function": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
- "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
- "license": "MIT",
- "dependencies": {
- "is-property": "^1.0.2"
- }
- },
- "node_modules/generator-function": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
- "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "license": "ISC",
- "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-nonce": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
- "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/get-own-enumerable-property-symbols": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
- "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
- "license": "ISC"
- },
- "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/get-symbol-description": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
- "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-tsconfig": {
- "version": "4.14.0",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
- "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "resolve-pkg-maps": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
- }
- },
- "node_modules/glob": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
- "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
- "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": "BlueOak-1.0.0",
- "dependencies": {
- "foreground-child": "^3.3.1",
- "jackspeak": "^4.1.1",
- "minimatch": "^10.1.1",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^2.0.0"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "engines": {
- "node": "20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/globalthis": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
- "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
- "license": "MIT",
- "dependencies": {
- "define-properties": "^1.2.1",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
- "node_modules/has-bigints": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
- "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
- "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "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",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hashery": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz",
- "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==",
- "license": "MIT",
- "dependencies": {
- "hookified": "^1.15.0"
- },
- "engines": {
- "node": ">=20"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
- "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/helmet": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz",
- "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==",
- "license": "MIT",
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/help-me": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
- "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==",
- "license": "MIT"
- },
- "node_modules/hookified": {
- "version": "1.15.1",
- "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz",
- "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==",
- "license": "MIT"
- },
- "node_modules/html-parse-stringify": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
- "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
- "license": "MIT",
- "dependencies": {
- "void-elements": "3.1.0"
- }
- },
- "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/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",
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/i18next": {
- "version": "26.0.8",
- "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.8.tgz",
- "integrity": "sha512-BRzLom0mhDhV9v0QhgUUHWQJuwFmnr1194xEcNLYD6ym8y8s542n4jXUvRLnhNTbh9PmpU6kGZamyuGHQMsGjw==",
- "funding": [
- {
- "type": "individual",
- "url": "https://www.locize.com/i18next"
- },
- {
- "type": "individual",
- "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
- },
- {
- "type": "individual",
- "url": "https://www.locize.com"
- }
- ],
- "license": "MIT",
- "peerDependencies": {
- "typescript": "^5 || ^6"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/i18next-browser-languagedetector": {
- "version": "8.2.1",
- "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz",
- "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.23.2"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/idb": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
- "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
- "license": "ISC"
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "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/input-otp": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz",
- "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==",
- "license": "MIT",
- "peerDependencies": {
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc"
- }
- },
- "node_modules/internal-slot": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
- "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "hasown": "^2.0.2",
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/internmap": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
- "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/invariant": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
- "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.0.0"
- }
- },
- "node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "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-array-buffer": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
- "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-async-function": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
- "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
- "license": "MIT",
- "dependencies": {
- "async-function": "^1.0.0",
- "call-bound": "^1.0.3",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-bigint": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
- "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
- "license": "MIT",
- "dependencies": {
- "has-bigints": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-boolean-object": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
- "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-data-view": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
- "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "get-intrinsic": "^1.2.6",
- "is-typed-array": "^1.1.13"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-date-object": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
- "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-finalizationregistry": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
- "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-generator-function": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
- "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.4",
- "generator-function": "^2.0.0",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-map": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
- "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
- "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
- "license": "MIT"
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
- "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-number-object": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
- "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-obj": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
- "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-property": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
- "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
- "license": "MIT"
- },
- "node_modules/is-regex": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
- "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-regexp": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
- "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-set": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
- "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
- "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-string": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
- "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
- "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "has-symbols": "^1.1.0",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
- "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
- "license": "MIT",
- "dependencies": {
- "which-typed-array": "^1.1.16"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakmap": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
- "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakref": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
- "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakset": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
- "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "license": "MIT"
- },
- "node_modules/isexe": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz",
- "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/jackspeak": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
- "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^9.0.0"
- },
- "engines": {
- "node": "20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/jake": {
- "version": "10.9.4",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz",
- "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==",
- "license": "Apache-2.0",
- "dependencies": {
- "async": "^3.2.6",
- "filelist": "^1.0.4",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "jake": "bin/cli.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/jiti": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
- "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
- "license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/joycon": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
- "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/js-md5": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.8.3.tgz",
- "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==",
- "license": "MIT"
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "license": "MIT"
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "license": "MIT"
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jsonfile": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
- "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/jsonpointer": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
- "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.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/jsonwebtoken/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "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/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/keyv": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
- "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
- "license": "MIT",
- "dependencies": {
- "@keyv/serialize": "^1.1.1"
- }
- },
- "node_modules/leven": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
- "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/libsignal": {
- "name": "@whiskeysockets/libsignal-node",
- "version": "2.0.1",
- "resolved": "git+ssh://git@github.com/whiskeysockets/libsignal-node.git#1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67",
- "license": "GPL-3.0",
- "dependencies": {
- "curve25519-js": "^0.0.4",
- "protobufjs": "6.8.8"
- }
- },
- "node_modules/libsignal/node_modules/@types/node": {
- "version": "10.17.60",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
- "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==",
- "license": "MIT"
- },
- "node_modules/libsignal/node_modules/long": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
- "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
- "license": "Apache-2.0"
- },
- "node_modules/libsignal/node_modules/protobufjs": {
- "version": "6.8.8",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz",
- "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.2",
- "@protobufjs/base64": "^1.1.2",
- "@protobufjs/codegen": "^2.0.4",
- "@protobufjs/eventemitter": "^1.1.0",
- "@protobufjs/fetch": "^1.1.0",
- "@protobufjs/float": "^1.0.2",
- "@protobufjs/inquire": "^1.1.0",
- "@protobufjs/path": "^1.1.2",
- "@protobufjs/pool": "^1.1.0",
- "@protobufjs/utf8": "^1.1.0",
- "@types/long": "^4.0.0",
- "@types/node": "^10.1.0",
- "long": "^4.0.0"
- },
- "bin": {
- "pbjs": "bin/pbjs",
- "pbts": "bin/pbts"
- }
- },
- "node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-android-arm64": "1.32.0",
- "lightningcss-darwin-arm64": "1.32.0",
- "lightningcss-darwin-x64": "1.32.0",
- "lightningcss-freebsd-x64": "1.32.0",
- "lightningcss-linux-arm-gnueabihf": "1.32.0",
- "lightningcss-linux-arm64-gnu": "1.32.0",
- "lightningcss-linux-arm64-musl": "1.32.0",
- "lightningcss-linux-x64-gnu": "1.32.0",
- "lightningcss-linux-x64-musl": "1.32.0",
- "lightningcss-win32-arm64-msvc": "1.32.0",
- "lightningcss-win32-x64-msvc": "1.32.0"
- }
- },
- "node_modules/lightningcss-android-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
- "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
- "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
- "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-freebsd-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
- "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
- "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
- "cpu": [
- "arm"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
- "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
- "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
- "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
- "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
- "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
- "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/linebreak": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
- "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
- "license": "MIT",
- "dependencies": {
- "base64-js": "0.0.8",
- "unicode-trie": "^2.0.0"
- }
- },
- "node_modules/linebreak/node_modules/base64-js": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
- "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "license": "MIT",
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/lodash": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
- "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
- "license": "MIT"
- },
- "node_modules/lodash.debounce": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
- "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/lodash.sortby": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
- "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
- "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"
- },
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
- }
- },
- "node_modules/loupe": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
- "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/lru.min": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz",
- "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==",
- "license": "MIT",
- "engines": {
- "bun": ">=1.0.0",
- "deno": ">=1.30.0",
- "node": ">=8.0.0"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wellwelwel"
- }
- },
- "node_modules/lucide-react": {
- "version": "0.468.0",
- "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz",
- "integrity": "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==",
- "license": "ISC",
- "peerDependencies": {
- "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
- }
- },
- "node_modules/magic-string": {
- "version": "0.30.21",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "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": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
- "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "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",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.5"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/mitt": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
- "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
- "license": "MIT"
- },
- "node_modules/motion-dom": {
- "version": "11.18.1",
- "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz",
- "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==",
- "license": "MIT",
- "dependencies": {
- "motion-utils": "^11.18.1"
- }
- },
- "node_modules/motion-utils": {
- "version": "11.18.1",
- "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz",
- "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==",
- "license": "MIT"
- },
- "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/music-metadata": {
- "version": "11.12.3",
- "resolved": "https://registry.npmjs.org/music-metadata/-/music-metadata-11.12.3.tgz",
- "integrity": "sha512-n6hSTZkuD59qWgHh6IP5dtDlDZQXoxk/bcA85Jywg8Z1iFrlNgl2+GTFgjZyn52W5UgQpV42V4XqrQZZAMbZTQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- },
- {
- "type": "buymeacoffee",
- "url": "https://buymeacoffee.com/borewit"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "@borewit/text-codec": "^0.2.2",
- "@tokenizer/token": "^0.3.0",
- "content-type": "^1.0.5",
- "debug": "^4.4.3",
- "file-type": "^21.3.1",
- "media-typer": "^1.1.0",
- "strtok3": "^10.3.4",
- "token-types": "^6.1.2",
- "uint8array-extras": "^1.5.0",
- "win-guid": "^0.2.1"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/music-metadata/node_modules/media-typer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
- "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/mysql2": {
- "version": "3.22.2",
- "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.22.2.tgz",
- "integrity": "sha512-snC/L6YoCJPFpozZo3p3hiOlt9ItQ7sCnLSziFLlIttEzsPhrdcPT8g21BiQ7Oqif25W4Xq1IFuBzBvoFYDf0Q==",
- "license": "MIT",
- "dependencies": {
- "aws-ssl-profiles": "^1.1.2",
- "denque": "^2.1.0",
- "generate-function": "^2.3.1",
- "iconv-lite": "^0.7.2",
- "long": "^5.3.2",
- "lru.min": "^1.1.4",
- "named-placeholders": "^1.1.6",
- "sql-escaper": "^1.3.3"
- },
- "engines": {
- "node": ">= 8.0"
- },
- "peerDependencies": {
- "@types/node": ">= 8"
- }
- },
- "node_modules/mysql2/node_modules/iconv-lite": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
- "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
- "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/named-placeholders": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz",
- "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==",
- "license": "MIT",
- "dependencies": {
- "lru.min": "^1.1.0"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/nanoid": {
- "version": "5.1.9",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.9.tgz",
- "integrity": "sha512-ZUvP7KeBLe3OZ1ypw6dI/TzYJuvHP77IM4Ry73waSQTLn8/g8rpdjfyVAh7t1/+FjBtG4lCP42MEbDxOsRpBMw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.js"
- },
- "engines": {
- "node": "^18 || >=20"
- }
- },
- "node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-releases": {
- "version": "2.0.38",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz",
- "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==",
- "license": "MIT"
- },
- "node_modules/nodemailer": {
- "version": "8.0.6",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.6.tgz",
- "integrity": "sha512-Nm2XeuDwwy2wi5A+8jPWwQwNzcjNjhWdE3pVLoXEusxJqCnAPAgnBGkSmiLknbnWuOF9qraRpYZjfxqtKZ4tPw==",
- "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-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/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
- "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0",
- "has-symbols": "^1.1.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/on-exit-leak-free": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
- "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "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/own-keys": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
- "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
- "license": "MIT",
- "dependencies": {
- "get-intrinsic": "^1.2.6",
- "object-keys": "^1.1.1",
- "safe-push-apply": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "license": "MIT",
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "license": "MIT",
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-queue": {
- "version": "9.1.2",
- "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.1.2.tgz",
- "integrity": "sha512-ktsDOALzTYTWWF1PbkNVg2rOt+HaOaMWJMUnt7T3qf5tvZ1L8dBW3tObzprBcXNMKkwj+yFSLqHso0x+UFcJXw==",
- "license": "MIT",
- "dependencies": {
- "eventemitter3": "^5.0.1",
- "p-timeout": "^7.0.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-queue/node_modules/eventemitter3": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
- "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
- "license": "MIT"
- },
- "node_modules/p-timeout": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz",
- "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==",
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "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/pako": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
- "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
- "license": "(MIT AND Zlib)"
- },
- "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-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "license": "MIT"
- },
- "node_modules/path-scurry": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
- "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^11.0.0",
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/path-scurry/node_modules/lru-cache": {
- "version": "11.3.5",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
- "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
- "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
- "license": "MIT"
- },
- "node_modules/pathe": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
- "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/pathval": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
- "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 14.16"
- }
- },
- "node_modules/pdfkit": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.18.0.tgz",
- "integrity": "sha512-NvUwSDZ0eYEzqAiWwVQkRkjYUkZ48kcsHuCO31ykqPPIVkwoSDjDGiwIgHHNtsiwls3z3P/zy4q00hl2chg2Ug==",
- "license": "MIT",
- "dependencies": {
- "@noble/ciphers": "^1.0.0",
- "@noble/hashes": "^1.6.0",
- "fontkit": "^2.0.4",
- "js-md5": "^0.8.3",
- "linebreak": "^1.1.0",
- "png-js": "^1.0.0"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pino": {
- "version": "10.3.1",
- "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz",
- "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==",
- "license": "MIT",
- "dependencies": {
- "@pinojs/redact": "^0.4.0",
- "atomic-sleep": "^1.0.0",
- "on-exit-leak-free": "^2.1.0",
- "pino-abstract-transport": "^3.0.0",
- "pino-std-serializers": "^7.0.0",
- "process-warning": "^5.0.0",
- "quick-format-unescaped": "^4.0.3",
- "real-require": "^0.2.0",
- "safe-stable-stringify": "^2.3.1",
- "sonic-boom": "^4.0.1",
- "thread-stream": "^4.0.0"
- },
- "bin": {
- "pino": "bin.js"
- }
- },
- "node_modules/pino-abstract-transport": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz",
- "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==",
- "license": "MIT",
- "dependencies": {
- "split2": "^4.0.0"
- }
- },
- "node_modules/pino-pretty": {
- "version": "13.1.3",
- "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz",
- "integrity": "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==",
- "license": "MIT",
- "dependencies": {
- "colorette": "^2.0.7",
- "dateformat": "^4.6.3",
- "fast-copy": "^4.0.0",
- "fast-safe-stringify": "^2.1.1",
- "help-me": "^5.0.0",
- "joycon": "^3.1.1",
- "minimist": "^1.2.6",
- "on-exit-leak-free": "^2.1.0",
- "pino-abstract-transport": "^3.0.0",
- "pump": "^3.0.0",
- "secure-json-parse": "^4.0.0",
- "sonic-boom": "^4.0.1",
- "strip-json-comments": "^5.0.2"
- },
- "bin": {
- "pino-pretty": "bin.js"
- }
- },
- "node_modules/pino-std-serializers": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz",
- "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==",
- "license": "MIT"
- },
- "node_modules/png-js": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.1.0.tgz",
- "integrity": "sha512-PM/uYGzGdNSzqeOgly68+6wKQDL1SY0a/N+OEa/+br6LnHWOAJB0Npiamnodfq3jd2LS/i2fMeOKSAILjA+m5Q==",
- "dependencies": {
- "browserify-zlib": "^0.2.0"
- }
- },
- "node_modules/pngjs": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
- "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
- "license": "MIT",
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/possible-typed-array-names": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
- "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.10",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
- "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.11",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss/node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/pretty-bytes": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz",
- "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==",
- "license": "MIT",
- "engines": {
- "node": "^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/process-warning": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
- "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "MIT"
- },
- "node_modules/prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- }
- },
- "node_modules/prop-types/node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "license": "MIT"
- },
- "node_modules/protobufjs": {
- "version": "7.5.5",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz",
- "integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.2",
- "@protobufjs/base64": "^1.1.2",
- "@protobufjs/codegen": "^2.0.4",
- "@protobufjs/eventemitter": "^1.1.0",
- "@protobufjs/fetch": "^1.1.0",
- "@protobufjs/float": "^1.0.2",
- "@protobufjs/inquire": "^1.1.0",
- "@protobufjs/path": "^1.1.2",
- "@protobufjs/pool": "^1.1.0",
- "@protobufjs/utf8": "^1.1.0",
- "@types/node": ">=13.7.0",
- "long": "^5.0.0"
- },
- "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/proxy-from-env": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
- "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/pump": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
- "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "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/qified": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/qified/-/qified-0.9.1.tgz",
- "integrity": "sha512-n7mar4T0xQ+39dE2vGTAlbxUEpndwPANH0kDef1/MYsB8Bba9wshkybIRx74qgcvKQPEWErf9AqAdYjhzY2Ilg==",
- "license": "MIT",
- "dependencies": {
- "hookified": "^2.1.1"
- },
- "engines": {
- "node": ">=20"
- }
- },
- "node_modules/qified/node_modules/hookified": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.1.1.tgz",
- "integrity": "sha512-AHb76R16GB5EsPBE2J7Ko5kiEyXwviB9P5SMrAKcuAu4vJPZttViAbj9+tZeaQE5zjDme+1vcHP78Yj/WoAveA==",
- "license": "MIT"
- },
- "node_modules/qrcode": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
- "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
- "license": "MIT",
- "dependencies": {
- "dijkstrajs": "^1.0.1",
- "pngjs": "^5.0.0",
- "yargs": "^15.3.1"
- },
- "bin": {
- "qrcode": "bin/qrcode"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/qrcode-terminal": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz",
- "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==",
- "bin": {
- "qrcode-terminal": "bin/qrcode-terminal.js"
- }
- },
- "node_modules/qrcode/node_modules/cliui": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
- "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^6.2.0"
- }
- },
- "node_modules/qrcode/node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/qrcode/node_modules/y18n": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
- "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
- "license": "ISC"
- },
- "node_modules/qrcode/node_modules/yargs": {
- "version": "15.4.1",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
- "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
- "license": "MIT",
- "dependencies": {
- "cliui": "^6.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^4.1.0",
- "get-caller-file": "^2.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^4.2.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^18.1.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/qrcode/node_modules/yargs-parser": {
- "version": "18.1.3",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
- "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
- "license": "ISC",
- "dependencies": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/qs": {
- "version": "6.14.2",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
- "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/quick-format-unescaped": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
- "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
- "license": "MIT"
- },
- "node_modules/randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
- "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "^5.1.0"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
- "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/react": {
- "version": "19.2.5",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz",
- "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-dom": {
- "version": "19.2.5",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz",
- "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.27.0"
- },
- "peerDependencies": {
- "react": "^19.2.5"
- }
- },
- "node_modules/react-fast-compare": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
- "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
- "license": "MIT"
- },
- "node_modules/react-helmet-async": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-3.0.0.tgz",
- "integrity": "sha512-nA3IEZfXiclgrz4KLxAhqJqIfFDuvzQwlKwpdmzZIuC1KNSghDEIXmyU0TKtbM+NafnkICcwx8CECFrZ/sL/1w==",
- "license": "Apache-2.0",
- "dependencies": {
- "invariant": "^2.2.4",
- "react-fast-compare": "^3.2.2",
- "shallowequal": "^1.1.0"
- },
- "peerDependencies": {
- "react": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/react-i18next": {
- "version": "17.0.4",
- "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.4.tgz",
- "integrity": "sha512-hQipmK4EF0y6RO6tt6WuqnmWpWYEXmQUUzecmMBuNsIgYd3smXcG4GtYPWhvgxn0pqMOItKlEO8H24HCs5hc3g==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.29.2",
- "html-parse-stringify": "^3.0.1",
- "use-sync-external-store": "^1.6.0"
- },
- "peerDependencies": {
- "i18next": ">= 26.0.1",
- "react": ">= 16.8.0",
- "typescript": "^5 || ^6"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- },
- "react-native": {
- "optional": true
- },
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
- "license": "MIT"
- },
- "node_modules/react-refresh": {
- "version": "0.17.0",
- "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
- "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-remove-scroll": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
- "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
- "license": "MIT",
- "dependencies": {
- "react-remove-scroll-bar": "^2.3.7",
- "react-style-singleton": "^2.2.3",
- "tslib": "^2.1.0",
- "use-callback-ref": "^1.3.3",
- "use-sidecar": "^1.1.3"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-remove-scroll-bar": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
- "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
- "license": "MIT",
- "dependencies": {
- "react-style-singleton": "^2.2.2",
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-smooth": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
- "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==",
- "license": "MIT",
- "dependencies": {
- "fast-equals": "^5.0.1",
- "prop-types": "^15.8.1",
- "react-transition-group": "^4.4.5"
- },
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/react-style-singleton": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
- "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
- "license": "MIT",
- "dependencies": {
- "get-nonce": "^1.0.0",
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-transition-group": {
- "version": "4.4.5",
- "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
- "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@babel/runtime": "^7.5.5",
- "dom-helpers": "^5.0.1",
- "loose-envify": "^1.4.0",
- "prop-types": "^15.6.2"
- },
- "peerDependencies": {
- "react": ">=16.6.0",
- "react-dom": ">=16.6.0"
- }
- },
- "node_modules/real-require": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
- "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
- "license": "MIT",
- "engines": {
- "node": ">= 12.13.0"
- }
- },
- "node_modules/recharts": {
- "version": "2.15.4",
- "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz",
- "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==",
- "license": "MIT",
- "dependencies": {
- "clsx": "^2.0.0",
- "eventemitter3": "^4.0.1",
- "lodash": "^4.17.21",
- "react-is": "^18.3.1",
- "react-smooth": "^4.0.4",
- "recharts-scale": "^0.4.4",
- "tiny-invariant": "^1.3.1",
- "victory-vendor": "^36.6.8"
- },
- "engines": {
- "node": ">=14"
- },
- "peerDependencies": {
- "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/recharts-scale": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
- "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
- "license": "MIT",
- "dependencies": {
- "decimal.js-light": "^2.4.1"
- }
- },
- "node_modules/reflect.getprototypeof": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
- "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.9",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "get-intrinsic": "^1.2.7",
- "get-proto": "^1.0.1",
- "which-builtin-type": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/regenerate": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
- "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
- "license": "MIT"
- },
- "node_modules/regenerate-unicode-properties": {
- "version": "10.2.2",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz",
- "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==",
- "license": "MIT",
- "dependencies": {
- "regenerate": "^1.4.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/regexp.prototype.flags": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
- "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-errors": "^1.3.0",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "set-function-name": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/regexparam": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-3.0.0.tgz",
- "integrity": "sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/regexpu-core": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz",
- "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==",
- "license": "MIT",
- "dependencies": {
- "regenerate": "^1.4.2",
- "regenerate-unicode-properties": "^10.2.2",
- "regjsgen": "^0.8.0",
- "regjsparser": "^0.13.0",
- "unicode-match-property-ecmascript": "^2.0.0",
- "unicode-match-property-value-ecmascript": "^2.2.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/regjsgen": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz",
- "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==",
- "license": "MIT"
- },
- "node_modules/regjsparser": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz",
- "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "jsesc": "~3.1.0"
- },
- "bin": {
- "regjsparser": "bin/parser"
- }
- },
- "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",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require-from-string": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require-main-filename": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
- "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
- "license": "ISC"
- },
- "node_modules/resolve": {
- "version": "1.22.12",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
- "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "is-core-module": "^2.16.1",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/resolve-pkg-maps": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
- "devOptional": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
- }
- },
- "node_modules/restructure": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz",
- "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
- "license": "MIT"
- },
- "node_modules/rollup": {
- "version": "4.60.2",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz",
- "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==",
- "license": "MIT",
- "dependencies": {
- "@types/estree": "1.0.8"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.60.2",
- "@rollup/rollup-android-arm64": "4.60.2",
- "@rollup/rollup-darwin-arm64": "4.60.2",
- "@rollup/rollup-darwin-x64": "4.60.2",
- "@rollup/rollup-freebsd-arm64": "4.60.2",
- "@rollup/rollup-freebsd-x64": "4.60.2",
- "@rollup/rollup-linux-arm-gnueabihf": "4.60.2",
- "@rollup/rollup-linux-arm-musleabihf": "4.60.2",
- "@rollup/rollup-linux-arm64-gnu": "4.60.2",
- "@rollup/rollup-linux-arm64-musl": "4.60.2",
- "@rollup/rollup-linux-loong64-gnu": "4.60.2",
- "@rollup/rollup-linux-loong64-musl": "4.60.2",
- "@rollup/rollup-linux-ppc64-gnu": "4.60.2",
- "@rollup/rollup-linux-ppc64-musl": "4.60.2",
- "@rollup/rollup-linux-riscv64-gnu": "4.60.2",
- "@rollup/rollup-linux-riscv64-musl": "4.60.2",
- "@rollup/rollup-linux-s390x-gnu": "4.60.2",
- "@rollup/rollup-linux-x64-gnu": "4.60.2",
- "@rollup/rollup-linux-x64-musl": "4.60.2",
- "@rollup/rollup-openbsd-x64": "4.60.2",
- "@rollup/rollup-openharmony-arm64": "4.60.2",
- "@rollup/rollup-win32-arm64-msvc": "4.60.2",
- "@rollup/rollup-win32-ia32-msvc": "4.60.2",
- "@rollup/rollup-win32-x64-gnu": "4.60.2",
- "@rollup/rollup-win32-x64-msvc": "4.60.2",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/rxjs": {
- "version": "7.8.2",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
- "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
- "node_modules/safe-array-concat": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz",
- "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.9",
- "call-bound": "^1.0.4",
- "get-intrinsic": "^1.3.0",
- "has-symbols": "^1.1.0",
- "isarray": "^2.0.5"
- },
- "engines": {
- "node": ">=0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/safe-push-apply": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
- "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "isarray": "^2.0.5"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-regex-test": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
- "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "is-regex": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-stable-stringify": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
- "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "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/scheduler": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
- "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
- "license": "MIT"
- },
- "node_modules/scmp": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz",
- "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==",
- "deprecated": "Just use Node.js's crypto.timingSafeEqual()",
- "license": "BSD-3-Clause"
- },
- "node_modules/secure-json-parse": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz",
- "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/send": {
- "version": "0.19.2",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
- "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.1",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "~2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "~2.0.2"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/send/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/serialize-javascript": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
- "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "randombytes": "^2.1.0"
- }
- },
- "node_modules/serve-static": {
- "version": "1.16.3",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
- "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "~0.19.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "license": "ISC"
- },
- "node_modules/set-function-length": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
- "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/set-function-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
- "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/set-proto": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
- "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/shallowequal": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
- "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
- "license": "MIT"
- },
- "node_modules/sharp": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
- "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "peer": true,
- "dependencies": {
- "@img/colour": "^1.0.0",
- "detect-libc": "^2.1.2",
- "semver": "^7.7.3"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.34.5",
- "@img/sharp-darwin-x64": "0.34.5",
- "@img/sharp-libvips-darwin-arm64": "1.2.4",
- "@img/sharp-libvips-darwin-x64": "1.2.4",
- "@img/sharp-libvips-linux-arm": "1.2.4",
- "@img/sharp-libvips-linux-arm64": "1.2.4",
- "@img/sharp-libvips-linux-ppc64": "1.2.4",
- "@img/sharp-libvips-linux-riscv64": "1.2.4",
- "@img/sharp-libvips-linux-s390x": "1.2.4",
- "@img/sharp-libvips-linux-x64": "1.2.4",
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
- "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
- "@img/sharp-linux-arm": "0.34.5",
- "@img/sharp-linux-arm64": "0.34.5",
- "@img/sharp-linux-ppc64": "0.34.5",
- "@img/sharp-linux-riscv64": "0.34.5",
- "@img/sharp-linux-s390x": "0.34.5",
- "@img/sharp-linux-x64": "0.34.5",
- "@img/sharp-linuxmusl-arm64": "0.34.5",
- "@img/sharp-linuxmusl-x64": "0.34.5",
- "@img/sharp-wasm32": "0.34.5",
- "@img/sharp-win32-arm64": "0.34.5",
- "@img/sharp-win32-ia32": "0.34.5",
- "@img/sharp-win32-x64": "0.34.5"
- }
- },
- "node_modules/sharp/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
- "license": "ISC",
- "peer": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "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/shell-quote": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
- "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.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/siginfo": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
- "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
- "dev": true,
- "license": "ISC"
- },
- "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/smob": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/smob/-/smob-1.6.1.tgz",
- "integrity": "sha512-KAkBqZl3c2GvNgNhcoyJae1aKldDW0LO279wF9bk1PnluRTETKBq0WyzRXxEhoQLk56yHaOY4JCBEKDuJIET5g==",
- "license": "MIT",
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/socket.io": {
- "version": "4.8.3",
- "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz",
- "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.4",
- "base64id": "~2.0.0",
- "cors": "~2.8.5",
- "debug": "~4.4.1",
- "engine.io": "~6.6.0",
- "socket.io-adapter": "~2.5.2",
- "socket.io-parser": "~4.2.4"
- },
- "engines": {
- "node": ">=10.2.0"
- }
- },
- "node_modules/socket.io-adapter": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz",
- "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "~4.4.1",
- "ws": "~8.18.3"
- }
- },
- "node_modules/socket.io-client": {
- "version": "4.8.3",
- "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz",
- "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==",
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.4.1",
- "engine.io-client": "~6.6.1",
- "socket.io-parser": "~4.2.4"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/socket.io-parser": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz",
- "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==",
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.4.1"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/sonic-boom": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz",
- "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==",
- "license": "MIT",
- "dependencies": {
- "atomic-sleep": "^1.0.0"
- }
- },
- "node_modules/sonner": {
- "version": "1.7.4",
- "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.7.4.tgz",
- "integrity": "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw==",
- "license": "MIT",
- "peerDependencies": {
- "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
- "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "node_modules/sourcemap-codec": {
- "version": "1.4.8",
- "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
- "deprecated": "Please use @jridgewell/sourcemap-codec instead",
- "license": "MIT"
- },
- "node_modules/split2": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
- "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
- "license": "ISC",
- "engines": {
- "node": ">= 10.x"
- }
- },
- "node_modules/sql-escaper": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.3.3.tgz",
- "integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==",
- "license": "MIT",
- "engines": {
- "bun": ">=1.0.0",
- "deno": ">=2.0.0",
- "node": ">=12.0.0"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/mysqljs/sql-escaper?sponsor=1"
- }
- },
- "node_modules/stackback": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
- "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
- "dev": true,
- "license": "MIT"
- },
- "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/std-env": {
- "version": "3.10.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
- "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/stop-iteration-iterator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
- "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "internal-slot": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "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/string.prototype.matchall": {
- "version": "4.0.12",
- "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
- "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.6",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "get-intrinsic": "^1.2.6",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "internal-slot": "^1.1.0",
- "regexp.prototype.flags": "^1.5.3",
- "set-function-name": "^2.0.2",
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trim": {
- "version": "1.2.10",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
- "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.2",
- "define-data-property": "^1.1.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-object-atoms": "^1.0.0",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimend": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
- "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.2",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
- "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/stringify-object": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
- "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "get-own-enumerable-property-symbols": "^3.0.0",
- "is-obj": "^1.0.1",
- "is-regexp": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "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-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz",
- "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz",
- "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==",
- "license": "MIT",
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/stripe": {
- "version": "22.1.0",
- "resolved": "https://registry.npmjs.org/stripe/-/stripe-22.1.0.tgz",
- "integrity": "sha512-w/xHyJGxXWnLPbNHG13sz/fae0MrFGC80Oz7YbICQymbfpqfEcsoG+6yG+9BWb81PWc4rrkeSO4wmTcmefmbLw==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "@types/node": ">=18"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- }
- }
- },
- "node_modules/strtok3": {
- "version": "10.3.5",
- "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz",
- "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==",
- "license": "MIT",
- "dependencies": {
- "@tokenizer/token": "^0.3.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/superagent": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz",
- "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "component-emitter": "^1.3.1",
- "cookiejar": "^2.1.4",
- "debug": "^4.3.7",
- "fast-safe-stringify": "^2.1.1",
- "form-data": "^4.0.5",
- "formidable": "^3.5.4",
- "methods": "^1.1.2",
- "mime": "2.6.0",
- "qs": "^6.14.1"
- },
- "engines": {
- "node": ">=14.18.0"
- }
- },
- "node_modules/superagent/node_modules/mime": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
- "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/supertest": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz",
- "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cookie-signature": "^1.2.2",
- "methods": "^1.1.2",
- "superagent": "^10.3.0"
- },
- "engines": {
- "node": ">=14.18.0"
- }
- },
- "node_modules/supertest/node_modules/cookie-signature": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
- "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.6.0"
- }
- },
- "node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tailwind-merge": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz",
- "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/dcastil"
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.4.tgz",
- "integrity": "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
- "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/temp-dir": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
- "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tempy": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz",
- "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==",
- "license": "MIT",
- "dependencies": {
- "is-stream": "^2.0.0",
- "temp-dir": "^2.0.0",
- "type-fest": "^0.16.0",
- "unique-string": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/terser": {
- "version": "5.46.2",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.2.tgz",
- "integrity": "sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "@jridgewell/source-map": "^0.3.3",
- "acorn": "^8.15.0",
- "commander": "^2.20.0",
- "source-map-support": "~0.5.20"
- },
- "bin": {
- "terser": "bin/terser"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/thread-stream": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz",
- "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==",
- "license": "MIT",
- "dependencies": {
- "real-require": "^0.2.0"
- },
- "engines": {
- "node": ">=20"
- }
- },
- "node_modules/tiny-inflate": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
- "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
- "license": "MIT"
- },
- "node_modules/tiny-invariant": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
- "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
- "license": "MIT"
- },
- "node_modules/tinybench": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
- "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/tinyexec": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
- "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/tinyglobby": {
- "version": "0.2.16",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
- "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/tinypool": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
- "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- }
- },
- "node_modules/tinyrainbow": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
- "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/tinyspy": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
- "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/token-types": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz",
- "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==",
- "license": "MIT",
- "dependencies": {
- "@borewit/text-codec": "^0.2.1",
- "@tokenizer/token": "^0.3.0",
- "ieee754": "^1.2.1"
- },
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/tr46": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
- "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==",
- "license": "MIT",
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/tree-kill": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
- "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "tree-kill": "cli.js"
- }
- },
- "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/tsx": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
- "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "~0.27.0",
- "get-tsconfig": "^4.7.5"
- },
- "bin": {
- "tsx": "dist/cli.mjs"
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
- "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
- "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
- "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
- "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
- "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
- "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
- "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
- "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
- "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
- "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
- "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
- "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
- "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
- "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
- "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
- "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
- "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
- "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
- "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
- "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
- "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
- "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
- "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/esbuild": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
- "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
- "devOptional": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.27.7",
- "@esbuild/android-arm": "0.27.7",
- "@esbuild/android-arm64": "0.27.7",
- "@esbuild/android-x64": "0.27.7",
- "@esbuild/darwin-arm64": "0.27.7",
- "@esbuild/darwin-x64": "0.27.7",
- "@esbuild/freebsd-arm64": "0.27.7",
- "@esbuild/freebsd-x64": "0.27.7",
- "@esbuild/linux-arm": "0.27.7",
- "@esbuild/linux-arm64": "0.27.7",
- "@esbuild/linux-ia32": "0.27.7",
- "@esbuild/linux-loong64": "0.27.7",
- "@esbuild/linux-mips64el": "0.27.7",
- "@esbuild/linux-ppc64": "0.27.7",
- "@esbuild/linux-riscv64": "0.27.7",
- "@esbuild/linux-s390x": "0.27.7",
- "@esbuild/linux-x64": "0.27.7",
- "@esbuild/netbsd-arm64": "0.27.7",
- "@esbuild/netbsd-x64": "0.27.7",
- "@esbuild/openbsd-arm64": "0.27.7",
- "@esbuild/openbsd-x64": "0.27.7",
- "@esbuild/openharmony-arm64": "0.27.7",
- "@esbuild/sunos-x64": "0.27.7",
- "@esbuild/win32-arm64": "0.27.7",
- "@esbuild/win32-ia32": "0.27.7",
- "@esbuild/win32-x64": "0.27.7"
- }
- },
- "node_modules/twilio": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/twilio/-/twilio-6.0.0.tgz",
- "integrity": "sha512-MAie5DJ3KLpcKlDaYtNzsKMQXcCi+YHWKvZjuSpm27vJAO/l8PanJA0LkkJ03sbh+Kwe5NeL0Q2+y6IjNUYeUA==",
- "license": "MIT",
- "dependencies": {
- "axios": "^1.13.5",
- "dayjs": "^1.11.9",
- "https-proxy-agent": "^5.0.0",
- "jsonwebtoken": "^9.0.3",
- "qs": "^6.14.1",
- "scmp": "^2.1.0",
- "xmlbuilder": "^13.0.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/type-fest": {
- "version": "0.16.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
- "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==",
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "license": "MIT",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typed-array-buffer": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
- "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-typed-array": "^1.1.14"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typed-array-byte-length": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
- "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "for-each": "^0.3.3",
- "gopd": "^1.2.0",
- "has-proto": "^1.2.0",
- "is-typed-array": "^1.1.14"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-byte-offset": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
- "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
- "license": "MIT",
- "dependencies": {
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "for-each": "^0.3.3",
- "gopd": "^1.2.0",
- "has-proto": "^1.2.0",
- "is-typed-array": "^1.1.15",
- "reflect.getprototypeof": "^1.0.9"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-length": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
- "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "is-typed-array": "^1.1.13",
- "possible-typed-array-names": "^1.0.0",
- "reflect.getprototypeof": "^1.0.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typescript": {
- "version": "5.9.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
- "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/uint8array-extras": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
- "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/unbox-primitive": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
- "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.1.0",
- "which-boxed-primitive": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/undici-types": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
- "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "license": "MIT"
- },
- "node_modules/unicode-canonical-property-names-ecmascript": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
- "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
- "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
- "license": "MIT",
- "dependencies": {
- "unicode-canonical-property-names-ecmascript": "^2.0.0",
- "unicode-property-aliases-ecmascript": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-value-ecmascript": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz",
- "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-properties": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
- "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.0",
- "unicode-trie": "^2.0.0"
- }
- },
- "node_modules/unicode-property-aliases-ecmascript": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz",
- "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-trie": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
- "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
- "license": "MIT",
- "dependencies": {
- "pako": "^0.2.5",
- "tiny-inflate": "^1.0.0"
- }
- },
- "node_modules/unicode-trie/node_modules/pako": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
- "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
- "license": "MIT"
- },
- "node_modules/unique-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
- "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
- "license": "MIT",
- "dependencies": {
- "crypto-random-string": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/upath": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
- "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
- "license": "MIT",
- "engines": {
- "node": ">=4",
- "yarn": "*"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
- "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/use-callback-ref": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
- "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/use-sidecar": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
- "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
- "license": "MIT",
- "dependencies": {
- "detect-node-es": "^1.1.0",
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/use-sync-external-store": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
- "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
- "license": "MIT",
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/victory-vendor": {
- "version": "36.9.2",
- "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
- "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
- "license": "MIT AND ISC",
- "dependencies": {
- "@types/d3-array": "^3.0.3",
- "@types/d3-ease": "^3.0.0",
- "@types/d3-interpolate": "^3.0.1",
- "@types/d3-scale": "^4.0.2",
- "@types/d3-shape": "^3.1.0",
- "@types/d3-time": "^3.0.0",
- "@types/d3-timer": "^3.0.0",
- "d3-array": "^3.1.6",
- "d3-ease": "^3.0.1",
- "d3-interpolate": "^3.0.1",
- "d3-scale": "^4.0.2",
- "d3-shape": "^3.1.0",
- "d3-time": "^3.0.0",
- "d3-timer": "^3.0.1"
- }
- },
- "node_modules/vite": {
- "version": "6.4.2",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz",
- "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==",
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.25.0",
- "fdir": "^6.4.4",
- "picomatch": "^4.0.2",
- "postcss": "^8.5.3",
- "rollup": "^4.34.9",
- "tinyglobby": "^0.2.13"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "jiti": ">=1.21.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- },
- "node_modules/vite-node": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz",
- "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cac": "^6.7.14",
- "debug": "^4.3.7",
- "es-module-lexer": "^1.5.4",
- "pathe": "^1.1.2",
- "vite": "^5.0.0"
- },
- "bin": {
- "vite-node": "vite-node.mjs"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
- "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/android-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
- "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/android-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
- "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/android-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
- "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/darwin-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
- "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
- "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
- "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
- "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
- "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-loong64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
- "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
- "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
- "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
- "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-s390x": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
- "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/linux-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
- "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
- "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/sunos-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
- "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/win32-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
- "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/win32-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
- "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/@esbuild/win32-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
- "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite-node/node_modules/esbuild": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
- "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.21.5",
- "@esbuild/android-arm": "0.21.5",
- "@esbuild/android-arm64": "0.21.5",
- "@esbuild/android-x64": "0.21.5",
- "@esbuild/darwin-arm64": "0.21.5",
- "@esbuild/darwin-x64": "0.21.5",
- "@esbuild/freebsd-arm64": "0.21.5",
- "@esbuild/freebsd-x64": "0.21.5",
- "@esbuild/linux-arm": "0.21.5",
- "@esbuild/linux-arm64": "0.21.5",
- "@esbuild/linux-ia32": "0.21.5",
- "@esbuild/linux-loong64": "0.21.5",
- "@esbuild/linux-mips64el": "0.21.5",
- "@esbuild/linux-ppc64": "0.21.5",
- "@esbuild/linux-riscv64": "0.21.5",
- "@esbuild/linux-s390x": "0.21.5",
- "@esbuild/linux-x64": "0.21.5",
- "@esbuild/netbsd-x64": "0.21.5",
- "@esbuild/openbsd-x64": "0.21.5",
- "@esbuild/sunos-x64": "0.21.5",
- "@esbuild/win32-arm64": "0.21.5",
- "@esbuild/win32-ia32": "0.21.5",
- "@esbuild/win32-x64": "0.21.5"
- }
- },
- "node_modules/vite-node/node_modules/vite": {
- "version": "5.4.21",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
- "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.21.3",
- "postcss": "^8.4.43",
- "rollup": "^4.20.0"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || >=20.0.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/vite-plugin-pwa": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-1.2.0.tgz",
- "integrity": "sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.6",
- "pretty-bytes": "^6.1.1",
- "tinyglobby": "^0.2.10",
- "workbox-build": "^7.4.0",
- "workbox-window": "^7.4.0"
- },
- "engines": {
- "node": ">=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- },
- "peerDependencies": {
- "@vite-pwa/assets-generator": "^1.0.0",
- "vite": "^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",
- "workbox-build": "^7.4.0",
- "workbox-window": "^7.4.0"
- },
- "peerDependenciesMeta": {
- "@vite-pwa/assets-generator": {
- "optional": true
- }
- }
- },
- "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
- "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
- "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
- "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
- "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
- "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
- "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
- "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
- "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
- "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
- "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
- "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-loong64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
- "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
- "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
- "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
- "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-s390x": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
- "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
- "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
- "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
- "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
- "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/sunos-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
- "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
- "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
- "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
- "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/esbuild": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
- "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.12",
- "@esbuild/android-arm": "0.25.12",
- "@esbuild/android-arm64": "0.25.12",
- "@esbuild/android-x64": "0.25.12",
- "@esbuild/darwin-arm64": "0.25.12",
- "@esbuild/darwin-x64": "0.25.12",
- "@esbuild/freebsd-arm64": "0.25.12",
- "@esbuild/freebsd-x64": "0.25.12",
- "@esbuild/linux-arm": "0.25.12",
- "@esbuild/linux-arm64": "0.25.12",
- "@esbuild/linux-ia32": "0.25.12",
- "@esbuild/linux-loong64": "0.25.12",
- "@esbuild/linux-mips64el": "0.25.12",
- "@esbuild/linux-ppc64": "0.25.12",
- "@esbuild/linux-riscv64": "0.25.12",
- "@esbuild/linux-s390x": "0.25.12",
- "@esbuild/linux-x64": "0.25.12",
- "@esbuild/netbsd-arm64": "0.25.12",
- "@esbuild/netbsd-x64": "0.25.12",
- "@esbuild/openbsd-arm64": "0.25.12",
- "@esbuild/openbsd-x64": "0.25.12",
- "@esbuild/openharmony-arm64": "0.25.12",
- "@esbuild/sunos-x64": "0.25.12",
- "@esbuild/win32-arm64": "0.25.12",
- "@esbuild/win32-ia32": "0.25.12",
- "@esbuild/win32-x64": "0.25.12"
- }
- },
- "node_modules/vitest": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz",
- "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/expect": "2.1.9",
- "@vitest/mocker": "2.1.9",
- "@vitest/pretty-format": "^2.1.9",
- "@vitest/runner": "2.1.9",
- "@vitest/snapshot": "2.1.9",
- "@vitest/spy": "2.1.9",
- "@vitest/utils": "2.1.9",
- "chai": "^5.1.2",
- "debug": "^4.3.7",
- "expect-type": "^1.1.0",
- "magic-string": "^0.30.12",
- "pathe": "^1.1.2",
- "std-env": "^3.8.0",
- "tinybench": "^2.9.0",
- "tinyexec": "^0.3.1",
- "tinypool": "^1.0.1",
- "tinyrainbow": "^1.2.0",
- "vite": "^5.0.0",
- "vite-node": "2.1.9",
- "why-is-node-running": "^2.3.0"
- },
- "bin": {
- "vitest": "vitest.mjs"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- },
- "peerDependencies": {
- "@edge-runtime/vm": "*",
- "@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "2.1.9",
- "@vitest/ui": "2.1.9",
- "happy-dom": "*",
- "jsdom": "*"
- },
- "peerDependenciesMeta": {
- "@edge-runtime/vm": {
- "optional": true
- },
- "@types/node": {
- "optional": true
- },
- "@vitest/browser": {
- "optional": true
- },
- "@vitest/ui": {
- "optional": true
- },
- "happy-dom": {
- "optional": true
- },
- "jsdom": {
- "optional": true
- }
- }
- },
- "node_modules/vitest/node_modules/@esbuild/aix-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
- "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/android-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
- "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/android-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
- "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/android-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
- "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/darwin-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/darwin-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
- "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
- "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/freebsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
- "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
- "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
- "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-loong64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
- "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-mips64el": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
- "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
- "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-riscv64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
- "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-s390x": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
- "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/linux-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/netbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
- "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/openbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
- "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/sunos-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
- "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/win32-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
- "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/win32-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
- "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@esbuild/win32-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
- "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vitest/node_modules/@vitest/mocker": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz",
- "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/spy": "2.1.9",
- "estree-walker": "^3.0.3",
- "magic-string": "^0.30.12"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- },
- "peerDependencies": {
- "msw": "^2.4.9",
- "vite": "^5.0.0"
- },
- "peerDependenciesMeta": {
- "msw": {
- "optional": true
- },
- "vite": {
- "optional": true
- }
- }
- },
- "node_modules/vitest/node_modules/esbuild": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
- "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.21.5",
- "@esbuild/android-arm": "0.21.5",
- "@esbuild/android-arm64": "0.21.5",
- "@esbuild/android-x64": "0.21.5",
- "@esbuild/darwin-arm64": "0.21.5",
- "@esbuild/darwin-x64": "0.21.5",
- "@esbuild/freebsd-arm64": "0.21.5",
- "@esbuild/freebsd-x64": "0.21.5",
- "@esbuild/linux-arm": "0.21.5",
- "@esbuild/linux-arm64": "0.21.5",
- "@esbuild/linux-ia32": "0.21.5",
- "@esbuild/linux-loong64": "0.21.5",
- "@esbuild/linux-mips64el": "0.21.5",
- "@esbuild/linux-ppc64": "0.21.5",
- "@esbuild/linux-riscv64": "0.21.5",
- "@esbuild/linux-s390x": "0.21.5",
- "@esbuild/linux-x64": "0.21.5",
- "@esbuild/netbsd-x64": "0.21.5",
- "@esbuild/openbsd-x64": "0.21.5",
- "@esbuild/sunos-x64": "0.21.5",
- "@esbuild/win32-arm64": "0.21.5",
- "@esbuild/win32-ia32": "0.21.5",
- "@esbuild/win32-x64": "0.21.5"
- }
- },
- "node_modules/vitest/node_modules/vite": {
- "version": "5.4.21",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
- "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.21.3",
- "postcss": "^8.4.43",
- "rollup": "^4.20.0"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || >=20.0.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/void-elements": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
- "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/webidl-conversions": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
- "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
- "license": "BSD-2-Clause"
- },
- "node_modules/whatwg-url": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
- "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
- "license": "MIT",
- "dependencies": {
- "lodash.sortby": "^4.7.0",
- "tr46": "^1.0.1",
- "webidl-conversions": "^4.0.2"
- }
- },
- "node_modules/which": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
- "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^3.1.1"
- },
- "bin": {
- "node-which": "bin/which.js"
- },
- "engines": {
- "node": "^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/which-boxed-primitive": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
- "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
- "license": "MIT",
- "dependencies": {
- "is-bigint": "^1.1.0",
- "is-boolean-object": "^1.2.1",
- "is-number-object": "^1.1.1",
- "is-string": "^1.1.1",
- "is-symbol": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-builtin-type": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
- "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "function.prototype.name": "^1.1.6",
- "has-tostringtag": "^1.0.2",
- "is-async-function": "^2.0.0",
- "is-date-object": "^1.1.0",
- "is-finalizationregistry": "^1.1.0",
- "is-generator-function": "^1.0.10",
- "is-regex": "^1.2.1",
- "is-weakref": "^1.0.2",
- "isarray": "^2.0.5",
- "which-boxed-primitive": "^1.1.0",
- "which-collection": "^1.0.2",
- "which-typed-array": "^1.1.16"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-collection": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
- "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
- "license": "MIT",
- "dependencies": {
- "is-map": "^2.0.3",
- "is-set": "^2.0.3",
- "is-weakmap": "^2.0.2",
- "is-weakset": "^2.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-module": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
- "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
- "license": "ISC"
- },
- "node_modules/which-typed-array": {
- "version": "1.1.20",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
- "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
- "license": "MIT",
- "dependencies": {
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "for-each": "^0.3.5",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/why-is-node-running": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
- "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "siginfo": "^2.0.0",
- "stackback": "0.0.2"
- },
- "bin": {
- "why-is-node-running": "cli.js"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/win-guid": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/win-guid/-/win-guid-0.2.1.tgz",
- "integrity": "sha512-gEIQU4mkgl2OPeoNrWflcJFJ3Ae2BPd4eCsHHA/XikslkIVms/nHhvnvzIZV7VLmBvtFlDOzLt9rrZT+n6D67A==",
- "license": "MIT"
- },
- "node_modules/workbox-background-sync": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.4.0.tgz",
- "integrity": "sha512-8CB9OxKAgKZKyNMwfGZ1XESx89GryWTfI+V5yEj8sHjFH8MFelUwYXEyldEK6M6oKMmn807GoJFUEA1sC4XS9w==",
- "license": "MIT",
- "dependencies": {
- "idb": "^7.0.1",
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-broadcast-update": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-7.4.0.tgz",
- "integrity": "sha512-+eZQwoktlvo62cI0b+QBr40v5XjighxPq3Fzo9AWMiAosmpG5gxRHgTbGGhaJv/q/MFVxwFNGh/UwHZ/8K88lA==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-build": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-7.4.0.tgz",
- "integrity": "sha512-Ntk1pWb0caOFIvwz/hfgrov/OJ45wPEhI5PbTywQcYjyZiVhT3UrwwUPl6TRYbTm4moaFYithYnl1lvZ8UjxcA==",
- "license": "MIT",
- "dependencies": {
- "@apideck/better-ajv-errors": "^0.3.1",
- "@babel/core": "^7.24.4",
- "@babel/preset-env": "^7.11.0",
- "@babel/runtime": "^7.11.2",
- "@rollup/plugin-babel": "^5.2.0",
- "@rollup/plugin-node-resolve": "^15.2.3",
- "@rollup/plugin-replace": "^2.4.1",
- "@rollup/plugin-terser": "^0.4.3",
- "@surma/rollup-plugin-off-main-thread": "^2.2.3",
- "ajv": "^8.6.0",
- "common-tags": "^1.8.0",
- "fast-json-stable-stringify": "^2.1.0",
- "fs-extra": "^9.0.1",
- "glob": "^11.0.1",
- "lodash": "^4.17.20",
- "pretty-bytes": "^5.3.0",
- "rollup": "^2.79.2",
- "source-map": "^0.8.0-beta.0",
- "stringify-object": "^3.3.0",
- "strip-comments": "^2.0.1",
- "tempy": "^0.6.0",
- "upath": "^1.2.0",
- "workbox-background-sync": "7.4.0",
- "workbox-broadcast-update": "7.4.0",
- "workbox-cacheable-response": "7.4.0",
- "workbox-core": "7.4.0",
- "workbox-expiration": "7.4.0",
- "workbox-google-analytics": "7.4.0",
- "workbox-navigation-preload": "7.4.0",
- "workbox-precaching": "7.4.0",
- "workbox-range-requests": "7.4.0",
- "workbox-recipes": "7.4.0",
- "workbox-routing": "7.4.0",
- "workbox-strategies": "7.4.0",
- "workbox-streams": "7.4.0",
- "workbox-sw": "7.4.0",
- "workbox-window": "7.4.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/@rollup/plugin-babel": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
- "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.10.4",
- "@rollup/pluginutils": "^3.1.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0",
- "@types/babel__core": "^7.1.9",
- "rollup": "^1.20.0||^2.0.0"
- },
- "peerDependenciesMeta": {
- "@types/babel__core": {
- "optional": true
- }
- }
- },
- "node_modules/workbox-build/node_modules/@rollup/plugin-replace": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz",
- "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==",
- "license": "MIT",
- "dependencies": {
- "@rollup/pluginutils": "^3.1.0",
- "magic-string": "^0.25.7"
- },
- "peerDependencies": {
- "rollup": "^1.20.0 || ^2.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/@rollup/pluginutils": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
- "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
- "license": "MIT",
- "dependencies": {
- "@types/estree": "0.0.39",
- "estree-walker": "^1.0.1",
- "picomatch": "^2.2.2"
- },
- "engines": {
- "node": ">= 8.0.0"
- },
- "peerDependencies": {
- "rollup": "^1.20.0||^2.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/@types/estree": {
- "version": "0.0.39",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
- "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
- "license": "MIT"
- },
- "node_modules/workbox-build/node_modules/estree-walker": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
- "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
- "license": "MIT"
- },
- "node_modules/workbox-build/node_modules/magic-string": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
- "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
- "license": "MIT",
- "dependencies": {
- "sourcemap-codec": "^1.4.8"
- }
- },
- "node_modules/workbox-build/node_modules/picomatch": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
- "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/workbox-build/node_modules/pretty-bytes": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
- "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/workbox-build/node_modules/rollup": {
- "version": "2.80.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.80.0.tgz",
- "integrity": "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==",
- "license": "MIT",
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=10.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/workbox-build/node_modules/source-map": {
- "version": "0.8.0-beta.0",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
- "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
- "deprecated": "The work that was done in this beta branch won't be included in future versions",
- "license": "BSD-3-Clause",
- "dependencies": {
- "whatwg-url": "^7.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/workbox-cacheable-response": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-7.4.0.tgz",
- "integrity": "sha512-0Fb8795zg/x23ISFkAc7lbWes6vbw34DGFIMw31cwuHPgDEC/5EYm6m/ZkylLX0EnEbbOyOCLjKgFS/Z5g0HeQ==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-core": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-7.4.0.tgz",
- "integrity": "sha512-6BMfd8tYEnN4baG4emG9U0hdXM4gGuDU3ectXuVHnj71vwxTFI7WOpQJC4siTOlVtGqCUtj0ZQNsrvi6kZZTAQ==",
- "license": "MIT"
- },
- "node_modules/workbox-expiration": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-7.4.0.tgz",
- "integrity": "sha512-V50p4BxYhtA80eOvulu8xVfPBgZbkxJ1Jr8UUn0rvqjGhLDqKNtfrDfjJKnLz2U8fO2xGQJTx/SKXNTzHOjnHw==",
- "license": "MIT",
- "dependencies": {
- "idb": "^7.0.1",
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-google-analytics": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-7.4.0.tgz",
- "integrity": "sha512-MVPXQslRF6YHkzGoFw1A4GIB8GrKym/A5+jYDUSL+AeJw4ytQGrozYdiZqUW1TPQHW8isBCBtyFJergUXyNoWQ==",
- "license": "MIT",
- "dependencies": {
- "workbox-background-sync": "7.4.0",
- "workbox-core": "7.4.0",
- "workbox-routing": "7.4.0",
- "workbox-strategies": "7.4.0"
- }
- },
- "node_modules/workbox-navigation-preload": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-7.4.0.tgz",
- "integrity": "sha512-etzftSgdQfjMcfPgbfaZCfM2QuR1P+4o8uCA2s4rf3chtKTq/Om7g/qvEOcZkG6v7JZOSOxVYQiOu6PbAZgU6w==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-precaching": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-7.4.0.tgz",
- "integrity": "sha512-VQs37T6jDqf1rTxUJZXRl3yjZMf5JX/vDPhmx2CPgDDKXATzEoqyRqhYnRoxl6Kr0rqaQlp32i9rtG5zTzIlNg==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0",
- "workbox-routing": "7.4.0",
- "workbox-strategies": "7.4.0"
- }
- },
- "node_modules/workbox-range-requests": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-7.4.0.tgz",
- "integrity": "sha512-3Vq854ZNuP6Y0KZOQWLaLC9FfM7ZaE+iuQl4VhADXybwzr4z/sMmnLgTeUZLq5PaDlcJBxYXQ3U91V7dwAIfvw==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-recipes": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-7.4.0.tgz",
- "integrity": "sha512-kOkWvsAn4H8GvAkwfJTbwINdv4voFoiE9hbezgB1sb/0NLyTG4rE7l6LvS8lLk5QIRIto+DjXLuAuG3Vmt3cxQ==",
- "license": "MIT",
- "dependencies": {
- "workbox-cacheable-response": "7.4.0",
- "workbox-core": "7.4.0",
- "workbox-expiration": "7.4.0",
- "workbox-precaching": "7.4.0",
- "workbox-routing": "7.4.0",
- "workbox-strategies": "7.4.0"
- }
- },
- "node_modules/workbox-routing": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-7.4.0.tgz",
- "integrity": "sha512-C/ooj5uBWYAhAqwmU8HYQJdOjjDKBp9MzTQ+otpMmd+q0eF59K+NuXUek34wbL0RFrIXe/KKT+tUWcZcBqxbHQ==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-strategies": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-7.4.0.tgz",
- "integrity": "sha512-T4hVqIi5A4mHi92+5EppMX3cLaVywDp8nsyUgJhOZxcfSV/eQofcOA6/EMo5rnTNmNTpw0rUgjAI6LaVullPpg==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/workbox-streams": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-7.4.0.tgz",
- "integrity": "sha512-QHPBQrey7hQbnTs5GrEVoWz7RhHJXnPT+12qqWM378orDMo5VMJLCkCM1cnCk+8Eq92lccx/VgRZ7WAzZWbSLg==",
- "license": "MIT",
- "dependencies": {
- "workbox-core": "7.4.0",
- "workbox-routing": "7.4.0"
- }
- },
- "node_modules/workbox-sw": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.4.0.tgz",
- "integrity": "sha512-ltU+Kr3qWR6BtbdlMnCjobZKzeV1hN+S6UvDywBrwM19TTyqA03X66dzw1tEIdJvQ4lYKkBFox6IAEhoSEZ8Xw==",
- "license": "MIT"
- },
- "node_modules/workbox-window": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-7.4.0.tgz",
- "integrity": "sha512-/bIYdBLAVsNR3v7gYGaV4pQW3M3kEPx5E8vDxGvxo6khTrGtSSCS7QiFKv9ogzBgZiy0OXLP9zO28U/1nF1mfw==",
- "license": "MIT",
- "dependencies": {
- "@types/trusted-types": "^2.0.2",
- "workbox-core": "7.4.0"
- }
- },
- "node_modules/wouter": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/wouter/-/wouter-3.9.0.tgz",
- "integrity": "sha512-sF/od/PIgqEQBQcrN7a2x3MX6MQE6nW0ygCfy9hQuUkuB28wEZuu/6M5GyqkrrEu9M6jxdkgE12yDFsQMKos4Q==",
- "license": "Unlicense",
- "dependencies": {
- "mitt": "^3.0.1",
- "regexparam": "^3.0.0",
- "use-sync-external-store": "^1.0.0"
- },
- "peerDependencies": {
- "react": ">=16.8.0"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "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/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/ws": {
- "version": "8.18.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
- "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/xmlbuilder": {
- "version": "13.0.2",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz",
- "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0"
- }
- },
- "node_modules/xmlhttprequest-ssl": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
- "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
- "engines": {
- "node": ">=0.4.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==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "license": "ISC"
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- }
- }
-}
diff --git a/package.json b/package.json
deleted file mode 100644
index de17366..0000000
--- a/package.json
+++ /dev/null
@@ -1,111 +0,0 @@
-{
- "name": "queue-med",
- "version": "1.0.0",
- "private": true,
- "type": "module",
- "description": "QueueMed — virtual waiting room for medical practices",
- "scripts": {
- "dev": "concurrently -k -n server,client -c blue,green \"pnpm:dev:server\" \"pnpm:dev:client\"",
- "dev:server": "tsx watch --env-file=.env server/_core/index.ts",
- "dev:client": "vite",
- "build": "vite build",
- "start": "NODE_ENV=production tsx server/_core/index.ts",
- "db:push": "drizzle-kit push",
- "db:generate": "drizzle-kit generate",
- "test": "vitest run",
- "typecheck": "tsc --noEmit"
- },
- "dependencies": {
- "@hapi/boom": "^10.0.1",
- "@radix-ui/react-alert-dialog": "^1.1.15",
- "@radix-ui/react-checkbox": "^1.1.3",
- "@radix-ui/react-dialog": "^1.1.4",
- "@radix-ui/react-dropdown-menu": "^2.1.4",
- "@radix-ui/react-label": "^2.1.1",
- "@radix-ui/react-popover": "^1.1.4",
- "@radix-ui/react-progress": "^1.1.1",
- "@radix-ui/react-radio-group": "^1.2.2",
- "@radix-ui/react-select": "^2.1.4",
- "@radix-ui/react-separator": "^1.1.1",
- "@radix-ui/react-slot": "^1.1.1",
- "@radix-ui/react-switch": "^1.1.2",
- "@radix-ui/react-tabs": "^1.1.2",
- "@radix-ui/react-toast": "^1.2.4",
- "@radix-ui/react-tooltip": "^1.1.6",
- "@stripe/stripe-js": "^9.3.1",
- "@tailwindcss/vite": "^4.0.0",
- "@tanstack/react-query": "^5.62.7",
- "@trpc/client": "11.0.0-rc.660",
- "@trpc/react-query": "11.0.0-rc.660",
- "@trpc/server": "11.0.0-rc.660",
- "@types/nodemailer": "^8.0.0",
- "@whiskeysockets/baileys": "7.0.0-rc.9",
- "bcryptjs": "^2.4.3",
- "class-variance-authority": "^0.7.1",
- "clsx": "^2.1.1",
- "cmdk": "^1.0.0",
- "cookie-parser": "^1.4.7",
- "cors": "^2.8.5",
- "date-fns": "^4.1.0",
- "drizzle-orm": "^0.38.2",
- "express": "^4.21.2",
- "express-rate-limit": "^8.4.1",
- "framer-motion": "^11.15.0",
- "helmet": "^8.1.0",
- "i18next": "^26.0.8",
- "i18next-browser-languagedetector": "^8.2.1",
- "input-otp": "^1.4.1",
- "jsonwebtoken": "^9.0.2",
- "lucide-react": "^0.468.0",
- "mysql2": "^3.11.5",
- "nanoid": "^5.0.9",
- "nodemailer": "^8.0.6",
- "p-queue": "^9.1.0",
- "pdfkit": "^0.18.0",
- "pino": "^10.3.1",
- "pino-pretty": "^13.1.3",
- "qrcode": "^1.5.4",
- "qrcode-terminal": "^0.12.0",
- "react": "^19.0.0",
- "react-dom": "^19.0.0",
- "react-helmet-async": "^3.0.0",
- "react-i18next": "^17.0.4",
- "recharts": "^2.15.0",
- "socket.io": "^4.8.1",
- "socket.io-client": "^4.8.1",
- "sonner": "^1.7.1",
- "stripe": "^22.1.0",
- "tailwind-merge": "^2.6.0",
- "tailwindcss": "^4.0.0",
- "twilio": "^6.0.0",
- "vite-plugin-pwa": "^1.2.0",
- "workbox-window": "^7.4.0",
- "wouter": "^3.3.5",
- "zod": "^3.24.1"
- },
- "devDependencies": {
- "@types/bcryptjs": "^2.4.6",
- "@types/cookie-parser": "^1.4.8",
- "@types/cors": "^2.8.17",
- "@types/express": "^4.17.21",
- "@types/jsonwebtoken": "^9.0.7",
- "@types/node": "^22.10.2",
- "@types/pdfkit": "^0.17.6",
- "@types/qrcode": "^1.5.5",
- "@types/react": "^19.0.2",
- "@types/react-dom": "^19.0.2",
- "@types/supertest": "^7.2.0",
- "@vitejs/plugin-react": "^4.3.4",
- "concurrently": "^9.1.1",
- "drizzle-kit": "^0.30.1",
- "supertest": "^7.2.2",
- "tsx": "^4.19.2",
- "typescript": "^5.7.2",
- "vite": "^6.0.0",
- "vitest": "^2.1.8"
- },
- "engines": {
- "node": ">=20"
- },
- "packageManager": "pnpm@9.15.0"
-}
diff --git a/scripts/backup-db.sh b/scripts/backup-db.sh
deleted file mode 100755
index 5bd9064..0000000
--- a/scripts/backup-db.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh
-# QueueMed — MySQL backup helper.
-#
-# Dumps the configured MySQL database into /app/data/backups (or $BACKUP_DIR)
-# with a timestamped filename, then prunes everything but the 7 most recent
-# backups. Designed to run inside the `app` container — schedule from the host
-# with `docker compose exec app /app/scripts/backup-db.sh` (cron, systemd, …).
-#
-# Required environment variables (already wired through docker-compose.yml):
-# MYSQL_HOST – hostname of the MySQL service (default: db)
-# MYSQL_DATABASE – database name to dump (default: queuemed)
-# MYSQL_USER – MySQL user (default: queuemed)
-# MYSQL_PASSWORD – MySQL password (required)
-# Optional:
-# BACKUP_DIR – override backup destination (default: /app/data/backups)
-# BACKUP_KEEP – number of backups to retain (default: 7)
-
-set -eu
-
-MYSQL_HOST="${MYSQL_HOST:-db}"
-MYSQL_DATABASE="${MYSQL_DATABASE:-queuemed}"
-MYSQL_USER="${MYSQL_USER:-queuemed}"
-BACKUP_DIR="${BACKUP_DIR:-/app/data/backups}"
-BACKUP_KEEP="${BACKUP_KEEP:-7}"
-
-if [ -z "${MYSQL_PASSWORD:-}" ]; then
- echo "[backup-db] MYSQL_PASSWORD is not set, aborting." >&2
- exit 1
-fi
-
-mkdir -p "$BACKUP_DIR"
-
-TIMESTAMP="$(date -u +%Y%m%dT%H%M%SZ)"
-OUT_FILE="$BACKUP_DIR/${MYSQL_DATABASE}-${TIMESTAMP}.sql.gz"
-TMP_FILE="${OUT_FILE}.partial"
-
-echo "[backup-db] dumping ${MYSQL_DATABASE} from ${MYSQL_HOST} -> ${OUT_FILE}"
-
-# --single-transaction keeps the dump consistent without locking InnoDB tables.
-# --quick streams rows row-by-row to keep memory bounded for large tables.
-mysqldump \
- --host="$MYSQL_HOST" \
- --user="$MYSQL_USER" \
- --password="$MYSQL_PASSWORD" \
- --single-transaction \
- --quick \
- --routines \
- --triggers \
- --no-tablespaces \
- --default-character-set=utf8mb4 \
- "$MYSQL_DATABASE" | gzip -9 > "$TMP_FILE"
-
-mv "$TMP_FILE" "$OUT_FILE"
-
-echo "[backup-db] backup written: $OUT_FILE ($(wc -c < "$OUT_FILE") bytes)"
-
-# ── Rotate: keep only the last $BACKUP_KEEP backups ─────────────────────────
-# `ls -1t` sorts by mtime descending; everything after the first $BACKUP_KEEP
-# entries is removed. Filenames are constrained to our prefix to avoid eating
-# unrelated files that might share the directory.
-cd "$BACKUP_DIR"
-ls -1t "${MYSQL_DATABASE}"-*.sql.gz 2>/dev/null \
- | awk -v keep="$BACKUP_KEEP" 'NR > keep' \
- | while IFS= read -r old; do
- echo "[backup-db] pruning old backup: $old"
- rm -f -- "$old"
- done
-
-echo "[backup-db] done."
diff --git a/server/_core/context.ts b/server/_core/context.ts
deleted file mode 100644
index 2b16553..0000000
--- a/server/_core/context.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { CreateExpressContextOptions } from "@trpc/server/adapters/express";
-import { getUserFromRequest } from "../auth.js";
-import type { User } from "../schema.js";
-
-export async function createContext({ req, res }: CreateExpressContextOptions) {
- const user = await getUserFromRequest(req);
- return {
- req,
- res,
- user,
- };
-}
-
-export type TrpcContext = {
- req: CreateExpressContextOptions["req"];
- res: CreateExpressContextOptions["res"];
- user: User | null;
-};
diff --git a/server/_core/index.ts b/server/_core/index.ts
deleted file mode 100644
index 4870bf7..0000000
--- a/server/_core/index.ts
+++ /dev/null
@@ -1,327 +0,0 @@
-import express from "express";
-import http from "node:http";
-import path from "node:path";
-import { fileURLToPath } from "node:url";
-import fs from "node:fs";
-import cors from "cors";
-import helmet from "helmet";
-import rateLimit from "express-rate-limit";
-import cookieParser from "cookie-parser";
-import { Server as SocketIOServer } from "socket.io";
-import { createExpressMiddleware } from "@trpc/server/adapters/express";
-import { appRouter } from "../routers.js";
-import { createContext } from "./context.js";
-import { authMiddleware, assertAuthEnv } from "../auth.js";
-import { getDb, pingDb } from "../db.js";
-import { startAutoAbsentJob, stopAutoAbsentJob } from "../services/autoAbsent.js";
-import {
- handleWebhook as handleStripeWebhook,
- isStripeConfigured,
- verifyAndConstructEvent,
-} from "../services/stripe.js";
-import { getActiveWhatsAppSessionsCount } from "../services/whatsapp.js";
-import { logger, childLogger } from "./logger.js";
-import { requestLogger } from "./requestLogger.js";
-
-const __dirname = path.dirname(fileURLToPath(import.meta.url));
-const ROOT = path.resolve(__dirname, "..", "..");
-const PORT = Number(process.env.PORT ?? 5000);
-const NODE_ENV = process.env.NODE_ENV ?? "development";
-const IS_PROD = NODE_ENV === "production";
-const BACKUP_DIR = process.env.BACKUP_DIR ?? "/app/data/backups";
-
-const PROD_ORIGINS = ["https://attente.cosmolan.fr"];
-const DEV_ORIGINS = [
- "http://localhost:5173",
- "http://127.0.0.1:5173",
- "http://localhost:5000",
- "http://127.0.0.1:5000",
-];
-const ALLOWED_ORIGINS = IS_PROD ? PROD_ORIGINS : DEV_ORIGINS;
-
-const serverLog = childLogger("server");
-const dbLog = childLogger("db");
-const stripeLog = childLogger("stripe");
-const trpcLog = childLogger("trpc");
-
-function readPackageVersion(): string {
- try {
- const pkgPath = path.resolve(ROOT, "package.json");
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8")) as { version?: string };
- return pkg.version ?? "0.0.0";
- } catch {
- return "0.0.0";
- }
-}
-const APP_VERSION = readPackageVersion();
-
-function getLastBackupTimestamp(): string | null {
- try {
- if (!fs.existsSync(BACKUP_DIR)) return null;
- const files = fs.readdirSync(BACKUP_DIR);
- let mostRecent = 0;
- for (const file of files) {
- const stat = fs.statSync(path.join(BACKUP_DIR, file));
- if (stat.isFile() && stat.mtimeMs > mostRecent) {
- mostRecent = stat.mtimeMs;
- }
- }
- return mostRecent > 0 ? new Date(mostRecent).toISOString() : null;
- } catch {
- return null;
- }
-}
-
-async function bootstrap() {
- // Fail fast if critical secrets are missing — refuse to start instead of
- // erroring lazily on the first authenticated request.
- assertAuthEnv();
-
- // Eagerly initialize database connection (warns early if DATABASE_URL missing)
- try {
- await getDb();
- dbLog.info("connected");
- } catch (err) {
- dbLog.error({ err }, "connection failed");
- }
-
- const app = express();
- // Required for express-rate-limit and secure cookies behind a reverse proxy
- app.set("trust proxy", 1);
- const httpServer = http.createServer(app);
-
- // ── Socket.io ────────────────────────────────────────────────────────────
- const io = new SocketIOServer(httpServer, {
- cors: {
- origin: ALLOWED_ORIGINS,
- credentials: true,
- },
- path: "/socket.io",
- });
- (globalThis as unknown as { __socketIo: SocketIOServer }).__socketIo = io;
-
- io.on("connection", (socket) => {
- socket.on("clinic:subscribe", (clinicId: number) => {
- if (typeof clinicId === "number") socket.join(`clinic:${clinicId}`);
- });
- socket.on("display:subscribe", (clinicId: number) => {
- if (typeof clinicId === "number") socket.join(`display:${clinicId}`);
- });
- socket.on("patient:subscribe", (patientToken: string) => {
- if (typeof patientToken === "string" && patientToken.length > 0) {
- socket.join(`patient:${patientToken}`);
- }
- });
- socket.on("clinic:unsubscribe", (clinicId: number) => {
- if (typeof clinicId === "number") socket.leave(`clinic:${clinicId}`);
- });
- socket.on("display:unsubscribe", (clinicId: number) => {
- if (typeof clinicId === "number") socket.leave(`display:${clinicId}`);
- });
- socket.on("patient:unsubscribe", (patientToken: string) => {
- if (typeof patientToken === "string") socket.leave(`patient:${patientToken}`);
- });
- });
-
- // ── Request logging (must come early to capture every API request) ───────
- app.use(requestLogger);
-
- // ── Security headers ─────────────────────────────────────────────────────
- // CSP is intentionally disabled here: it conflicts with the Vite dev server
- // and the inline assets generated by the SPA build. Re-enable once a proper
- // policy has been defined for the production bundle.
- app.use(
- helmet({
- contentSecurityPolicy: false,
- crossOriginEmbedderPolicy: false,
- })
- );
-
- // ── CORS ─────────────────────────────────────────────────────────────────
- app.use(
- cors({
- origin: (origin, callback) => {
- // Allow same-origin / non-browser requests (no Origin header)
- if (!origin) return callback(null, true);
- if (ALLOWED_ORIGINS.includes(origin)) return callback(null, true);
- return callback(new Error(`Origin not allowed by CORS: ${origin}`));
- },
- credentials: true,
- methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
- allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
- })
- );
-
- // ── Rate limiting ────────────────────────────────────────────────────────
- // Global limiter applied to the whole API surface.
- const globalLimiter = rateLimit({
- windowMs: 15 * 60 * 1000,
- max: 100,
- standardHeaders: true,
- legacyHeaders: false,
- message: { error: "Too many requests, please try again later." },
- });
-
- // Stricter limiter for authentication endpoints (login + register).
- const authLimiter = rateLimit({
- windowMs: 15 * 60 * 1000,
- max: 5,
- standardHeaders: true,
- legacyHeaders: false,
- skipSuccessfulRequests: true,
- message: { error: "Too many auth attempts, please try again later." },
- });
-
- // Password reset limiter — kept ready in case a reset endpoint is added.
- const passwordResetLimiter = rateLimit({
- windowMs: 60 * 60 * 1000,
- max: 3,
- standardHeaders: true,
- legacyHeaders: false,
- message: { error: "Too many password reset attempts, please try again later." },
- });
-
- // Apply auth limiter BEFORE the tRPC middleware so it short-circuits abuse.
- app.use(
- [
- "/api/trpc/auth.login",
- "/api/trpc/auth.register",
- ],
- authLimiter
- );
- app.use(
- [
- "/api/trpc/auth.requestPasswordReset",
- "/api/trpc/auth.resetPassword",
- "/api/trpc/auth.forgotPassword",
- ],
- passwordResetLimiter
- );
- app.use("/api", globalLimiter);
-
- // ── Stripe webhook (RAW body, must come BEFORE express.json) ─────────────
- app.post(
- "/api/stripe/webhook",
- express.raw({ type: "application/json", limit: "1mb" }),
- async (req, res) => {
- // If Stripe is not configured, silently acknowledge so the route never 500s.
- if (!(await isStripeConfigured())) {
- res.status(200).json({ received: true, configured: false });
- return;
- }
- const signature = req.headers["stripe-signature"];
- if (typeof signature !== "string") {
- res.status(400).json({ error: "Missing stripe-signature header" });
- return;
- }
- try {
- const event = await verifyAndConstructEvent(req.body as Buffer, signature);
- await handleStripeWebhook(event);
- res.status(200).json({ received: true });
- } catch (err) {
- stripeLog.error({ err }, "webhook error");
- const message = err instanceof Error ? err.message : "Webhook error";
- res.status(400).json({ error: message });
- }
- }
- );
-
- // ── Body / cookies / auth ────────────────────────────────────────────────
- app.use(express.json({ limit: "1mb" }));
- app.use(cookieParser());
- app.use(authMiddleware);
-
- // ── Health / readiness / liveness probes ─────────────────────────────────
- app.get("/api/health", async (_req, res) => {
- const dbStatus = await pingDb();
- const lastBackup = getLastBackupTimestamp();
- res.json({
- status: dbStatus.ok ? "ok" : "degraded",
- env: NODE_ENV,
- version: APP_VERSION,
- uptime: process.uptime(),
- ts: Date.now(),
- database: dbStatus.ok
- ? { status: "connected", latencyMs: dbStatus.latencyMs }
- : { status: "error", error: dbStatus.error },
- whatsapp: {
- activeSessions: getActiveWhatsAppSessionsCount(),
- },
- lastBackup,
- });
- });
-
- // k8s-style probes
- app.get("/api/live", (_req, res) => {
- res.json({ status: "ok", ts: Date.now() });
- });
-
- app.get("/api/ready", async (_req, res) => {
- const dbStatus = await pingDb();
- if (!dbStatus.ok) {
- res.status(503).json({ status: "not_ready", database: "error", error: dbStatus.error });
- return;
- }
- res.json({ status: "ready", database: "connected", latencyMs: dbStatus.latencyMs });
- });
-
- // ── tRPC ─────────────────────────────────────────────────────────────────
- app.use(
- "/api/trpc",
- createExpressMiddleware({
- router: appRouter,
- createContext,
- onError({ error, path }) {
- if (error.code === "INTERNAL_SERVER_ERROR") {
- trpcLog.error({ err: error, path }, "internal server error");
- } else {
- trpcLog.debug({ code: error.code, path, message: error.message }, "trpc error");
- }
- },
- })
- );
-
- // ── Static client (production) ───────────────────────────────────────────
- if (IS_PROD) {
- const clientDist = path.resolve(ROOT, "dist", "client");
- const indexHtml = path.resolve(clientDist, "index.html");
-
- if (fs.existsSync(clientDist)) {
- app.use(express.static(clientDist, { maxAge: "1h", index: false }));
- app.get("*", (req, res, next) => {
- if (req.path.startsWith("/api") || req.path.startsWith("/socket.io")) return next();
- if (!fs.existsSync(indexHtml)) return next();
- res.sendFile(indexHtml);
- });
- } else {
- serverLog.warn({ clientDist }, "static dist/client not found");
- }
- }
-
- // ── Error handler ────────────────────────────────────────────────────────
- app.use((err: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
- serverLog.error({ err }, "express error");
- res.status(500).json({ error: "Internal Server Error" });
- });
-
- httpServer.listen(PORT, () => {
- serverLog.info({ port: PORT, env: NODE_ENV, version: APP_VERSION }, "server listening");
- // Démarre le job qui marque les patients absents après N minutes sans réponse
- startAutoAbsentJob();
- });
-
- const shutdown = (signal: string) => {
- serverLog.info({ signal }, "received shutdown signal");
- stopAutoAbsentJob();
- io.close();
- httpServer.close(() => process.exit(0));
- setTimeout(() => process.exit(1), 10_000).unref();
- };
- process.on("SIGINT", () => shutdown("SIGINT"));
- process.on("SIGTERM", () => shutdown("SIGTERM"));
-}
-
-bootstrap().catch((err) => {
- logger.fatal({ err }, "server failed to start");
- process.exit(1);
-});
diff --git a/server/_core/logger.ts b/server/_core/logger.ts
deleted file mode 100644
index e3761ca..0000000
--- a/server/_core/logger.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Structured logger built on pino.
- *
- * - level: from LOG_LEVEL env var (default "info")
- * - dev: pretty-printed, colorized output
- * - prod: JSON output suitable for ingestion by log shippers
- *
- * Use child loggers (`logger.child({ component: "name" })`) to tag log lines
- * by subsystem so they remain easy to grep in production.
- */
-import pino, { type LoggerOptions } from "pino";
-
-const NODE_ENV = process.env.NODE_ENV ?? "development";
-const IS_PROD = NODE_ENV === "production";
-const LEVEL = process.env.LOG_LEVEL ?? "info";
-
-const baseOptions: LoggerOptions = {
- level: LEVEL,
- base: { env: NODE_ENV },
- timestamp: pino.stdTimeFunctions.isoTime,
-};
-
-const transport = IS_PROD
- ? undefined
- : {
- target: "pino-pretty",
- options: {
- colorize: true,
- translateTime: "SYS:HH:MM:ss.l",
- ignore: "pid,hostname,env",
- singleLine: false,
- },
- };
-
-export const logger = pino({
- ...baseOptions,
- ...(transport ? { transport } : {}),
-});
-
-export type Logger = typeof logger;
-
-export function childLogger(component: string, extra: Record = {}) {
- return logger.child({ component, ...extra });
-}
diff --git a/server/_core/requestLogger.ts b/server/_core/requestLogger.ts
deleted file mode 100644
index 0e258fa..0000000
--- a/server/_core/requestLogger.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Lightweight HTTP request logger that records method, url, status and duration
- * for every incoming request. Skips noisy probe endpoints to keep logs clean.
- */
-import type { Request, Response, NextFunction } from "express";
-import { childLogger } from "./logger.js";
-
-const httpLog = childLogger("http");
-
-const SKIP_PATHS = new Set(["/api/live", "/api/ready", "/api/health"]);
-
-export function requestLogger(req: Request, res: Response, next: NextFunction): void {
- if (SKIP_PATHS.has(req.path)) return next();
-
- const startNs = process.hrtime.bigint();
-
- res.on("finish", () => {
- const durationMs = Number((process.hrtime.bigint() - startNs) / 1_000_000n);
- const status = res.statusCode;
- const payload = {
- method: req.method,
- url: req.originalUrl ?? req.url,
- status,
- durationMs,
- };
- if (status >= 500) httpLog.error(payload, "request failed");
- else if (status >= 400) httpLog.warn(payload, "request error");
- else httpLog.info(payload, "request ok");
- });
-
- next();
-}
diff --git a/server/_core/trpc.ts b/server/_core/trpc.ts
deleted file mode 100644
index d84e2df..0000000
--- a/server/_core/trpc.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { initTRPC, TRPCError } from "@trpc/server";
-import type { TrpcContext } from "./context.js";
-import { isSubscriptionActive } from "../db.js";
-import { childLogger } from "./logger.js";
-
-const trpcLog = childLogger("trpc");
-
-const t = initTRPC.context().create({
- errorFormatter({ shape }) {
- return shape;
- },
-});
-
-export const router = t.router;
-export const middleware = t.middleware;
-
-// Timing middleware: logs every procedure call with its duration. Errors are
-// re-thrown so the existing error handlers in the express adapter still fire.
-const timing = t.middleware(async ({ path, type, next, ctx }) => {
- const start = Date.now();
- try {
- const result = await next();
- const durationMs = Date.now() - start;
- if (result.ok) {
- trpcLog.debug({ path, type, durationMs, userId: ctx.user?.id ?? null }, "procedure ok");
- } else {
- trpcLog.warn(
- { path, type, durationMs, userId: ctx.user?.id ?? null, code: result.error.code },
- "procedure error"
- );
- }
- return result;
- } catch (err) {
- const durationMs = Date.now() - start;
- trpcLog.error({ err, path, type, durationMs, userId: ctx.user?.id ?? null }, "procedure threw");
- throw err;
- }
-});
-
-export const publicProcedure = t.procedure.use(timing);
-
-const isAuthed = t.middleware(({ ctx, next }) => {
- if (!ctx.user) {
- throw new TRPCError({ code: "UNAUTHORIZED", message: "Authentication required" });
- }
- if (ctx.user.disabled) {
- throw new TRPCError({ code: "FORBIDDEN", message: "Compte désactivé" });
- }
- return next({
- ctx: {
- ...ctx,
- user: ctx.user,
- },
- });
-});
-
-export const protectedProcedure = t.procedure.use(isAuthed);
-
-const isAdmin = t.middleware(({ ctx, next }) => {
- if (!ctx.user) {
- throw new TRPCError({ code: "UNAUTHORIZED", message: "Authentication required" });
- }
- if (ctx.user.disabled) {
- throw new TRPCError({ code: "FORBIDDEN", message: "Compte désactivé" });
- }
- if (ctx.user.role !== "admin") {
- throw new TRPCError({ code: "FORBIDDEN", message: "Accès réservé aux administrateurs" });
- }
- return next({
- ctx: {
- ...ctx,
- user: ctx.user,
- },
- });
-});
-
-export const adminProcedure = t.procedure.use(isAdmin);
-
-const requireActiveSubscription = t.middleware(async ({ ctx, next }) => {
- if (!ctx.user) {
- throw new TRPCError({ code: "UNAUTHORIZED", message: "Authentication required" });
- }
- const active = await isSubscriptionActive(ctx.user.id);
- if (!active) {
- throw new TRPCError({
- code: "FORBIDDEN",
- message: "Subscription expired or inactive",
- });
- }
- return next({ ctx: { ...ctx, user: ctx.user } });
-});
-
-export const subscriptionProcedure = t.procedure.use(requireActiveSubscription);
diff --git a/server/auth.ts b/server/auth.ts
deleted file mode 100644
index 30a1f14..0000000
--- a/server/auth.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-import bcrypt from "bcryptjs";
-import jwt from "jsonwebtoken";
-import type { Request, Response, NextFunction } from "express";
-import { getUserById } from "./db.js";
-import type { User } from "./schema.js";
-
-const COOKIE_NAME = "qm_auth";
-const COOKIE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
-
-function getJwtSecret(): string {
- const secret = process.env.JWT_SECRET;
- if (!secret || secret.length < 32) {
- throw new Error(
- "JWT_SECRET is not set or is too short (>= 32 chars required). " +
- "Generate one with `openssl rand -hex 64` and set it in the environment."
- );
- }
- return secret;
-}
-
-/**
- * Fail-fast validation called from the server bootstrap so a misconfigured
- * deployment refuses to start instead of erroring lazily on the first login.
- */
-export function assertAuthEnv(): void {
- getJwtSecret();
-}
-
-export interface JwtPayload {
- sub: number;
- email: string;
- role: "user" | "admin";
-}
-
-// ─── Password hashing ────────────────────────────────────────────────────────
-export async function hashPassword(password: string): Promise {
- return bcrypt.hash(password, 12);
-}
-
-export async function verifyPassword(password: string, hash: string): Promise {
- return bcrypt.compare(password, hash);
-}
-
-// ─── JWT ─────────────────────────────────────────────────────────────────────
-export function createToken(user: Pick): string {
- const payload: JwtPayload = {
- sub: user.id,
- email: user.email,
- role: user.role,
- };
- return jwt.sign(payload, getJwtSecret(), { expiresIn: "7d" });
-}
-
-export function verifyToken(token: string): JwtPayload | null {
- try {
- const decoded = jwt.verify(token, getJwtSecret());
- if (typeof decoded === "string") return null;
- if (
- typeof decoded.sub !== "number" ||
- typeof decoded.email !== "string" ||
- (decoded.role !== "user" && decoded.role !== "admin")
- ) {
- return null;
- }
- return { sub: decoded.sub, email: decoded.email, role: decoded.role };
- } catch {
- return null;
- }
-}
-
-// ─── Cookie helpers ──────────────────────────────────────────────────────────
-export function setAuthCookie(res: Response, token: string): void {
- res.cookie(COOKIE_NAME, token, {
- httpOnly: true,
- secure: process.env.NODE_ENV === "production",
- sameSite: "lax",
- maxAge: COOKIE_MAX_AGE_MS,
- path: "/",
- });
-}
-
-export function clearAuthCookie(res: Response): void {
- res.clearCookie(COOKIE_NAME, { path: "/" });
-}
-
-export function readAuthCookie(req: Request): string | null {
- const cookies = (req as Request & { cookies?: Record }).cookies;
- if (cookies && typeof cookies[COOKIE_NAME] === "string") return cookies[COOKIE_NAME];
- const header = req.headers.authorization;
- if (header && header.startsWith("Bearer ")) return header.slice(7);
- return null;
-}
-
-// ─── User from request ───────────────────────────────────────────────────────
-export async function getUserFromRequest(req: Request): Promise {
- const token = readAuthCookie(req);
- if (!token) return null;
- const payload = verifyToken(token);
- if (!payload) return null;
- return getUserById(payload.sub);
-}
-
-// ─── Express middleware ──────────────────────────────────────────────────────
-export interface AuthedRequest extends Request {
- user?: User;
-}
-
-export async function authMiddleware(
- req: AuthedRequest,
- _res: Response,
- next: NextFunction
-): Promise {
- const user = await getUserFromRequest(req);
- if (user) req.user = user;
- next();
-}
-
-export function requireAuth(req: AuthedRequest, res: Response, next: NextFunction): void {
- if (!req.user) {
- res.status(401).json({ error: "Unauthorized" });
- return;
- }
- next();
-}
-
-export const AUTH_COOKIE_NAME = COOKIE_NAME;
diff --git a/server/db.ts b/server/db.ts
deleted file mode 100644
index 3cb18fb..0000000
--- a/server/db.ts
+++ /dev/null
@@ -1,1057 +0,0 @@
-import { drizzle, type MySql2Database } from "drizzle-orm/mysql2";
-import mysql from "mysql2/promise";
-import { and, asc, desc, eq, gte, inArray, like, lt, or, sql } from "drizzle-orm";
-import crypto from "node:crypto";
-import { childLogger } from "./_core/logger.js";
-import {
- users,
- subscriptions,
- clinics,
- queueEntries,
- analyticsEvents,
- whatsappCountryCodes,
- whatsappLogs,
- clinicMembers,
- appConfig,
- type User,
- type Subscription,
- type Clinic,
- type QueueEntry,
- type AnalyticsEvent,
- type ClinicMember,
- type AppConfig,
- type InsertUser,
- type InsertClinic,
- type InsertQueueEntry,
- type InsertWhatsappLog,
- type InsertClinicMember,
-} from "./schema.js";
-
-// ─── Connection pool (singleton) ─────────────────────────────────────────────
-let pool: mysql.Pool | null = null;
-let dbInstance: MySql2Database<{
- users: typeof users;
- subscriptions: typeof subscriptions;
- clinics: typeof clinics;
- queueEntries: typeof queueEntries;
- analyticsEvents: typeof analyticsEvents;
- whatsappCountryCodes: typeof whatsappCountryCodes;
- whatsappLogs: typeof whatsappLogs;
- clinicMembers: typeof clinicMembers;
- appConfig: typeof appConfig;
-}> | null = null;
-
-export async function getDb() {
- if (dbInstance) return dbInstance;
-
- const url = process.env.DATABASE_URL;
- if (!url) {
- throw new Error("DATABASE_URL is not set");
- }
-
- pool = mysql.createPool({
- uri: url,
- connectionLimit: 10,
- waitForConnections: true,
- enableKeepAlive: true,
- keepAliveInitialDelay: 10_000,
- });
-
- dbInstance = drizzle(pool, {
- schema: { users, subscriptions, clinics, queueEntries, analyticsEvents, whatsappCountryCodes, whatsappLogs, clinicMembers, appConfig },
- mode: "default",
- });
-
- return dbInstance;
-}
-
-export async function closeDb() {
- if (pool) {
- await pool.end();
- pool = null;
- dbInstance = null;
- }
-}
-
-/**
- * Ping the database with a trivial query. Used by health/readiness probes.
- * Returns the latency in ms on success, or an error message on failure.
- */
-export async function pingDb(): Promise<{ ok: true; latencyMs: number } | { ok: false; error: string }> {
- const start = Date.now();
- try {
- const db = await getDb();
- await db.execute(sql`SELECT 1`);
- return { ok: true, latencyMs: Date.now() - start };
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- return { ok: false, error: message };
- }
-}
-
-// ─── Users ───────────────────────────────────────────────────────────────────
-export async function getUserByEmail(email: string): Promise {
- const db = await getDb();
- const rows = await db.select().from(users).where(eq(users.email, email)).limit(1);
- return rows[0] ?? null;
-}
-
-export async function getUserById(id: number): Promise {
- const db = await getDb();
- const rows = await db.select().from(users).where(eq(users.id, id)).limit(1);
- return rows[0] ?? null;
-}
-
-export async function getUserByOpenId(openId: string): Promise {
- const db = await getDb();
- const rows = await db.select().from(users).where(eq(users.openId, openId)).limit(1);
- return rows[0] ?? null;
-}
-
-export async function createUser(data: InsertUser): Promise {
- const db = await getDb();
- const [result] = await db.insert(users).values(data);
- const id = (result as { insertId: number }).insertId;
- const created = await getUserById(id);
- if (!created) throw new Error("Failed to create user");
- return created;
-}
-
-export async function upsertUser(data: InsertUser): Promise {
- const existing = await getUserByEmail(data.email);
- if (existing) {
- const db = await getDb();
- await db
- .update(users)
- .set({ ...data, lastSignedIn: new Date() })
- .where(eq(users.id, existing.id));
- const refreshed = await getUserById(existing.id);
- if (!refreshed) throw new Error("Failed to refresh user");
- return refreshed;
- }
- return createUser(data);
-}
-
-export async function touchUserLogin(userId: number): Promise {
- const db = await getDb();
- await db.update(users).set({ lastSignedIn: new Date() }).where(eq(users.id, userId));
-}
-
-export async function setUserResetToken(
- userId: number,
- resetToken: string | null,
- resetTokenExpiry: Date | null
-): Promise {
- const db = await getDb();
- await db.update(users).set({ resetToken, resetTokenExpiry }).where(eq(users.id, userId));
-}
-
-export async function getUserByResetToken(token: string): Promise {
- const db = await getDb();
- const rows = await db.select().from(users).where(eq(users.resetToken, token)).limit(1);
- return rows[0] ?? null;
-}
-
-export async function updateUserPassword(userId: number, passwordHash: string): Promise {
- const db = await getDb();
- await db
- .update(users)
- .set({ passwordHash, resetToken: null, resetTokenExpiry: null })
- .where(eq(users.id, userId));
-}
-
-// ─── Subscriptions ───────────────────────────────────────────────────────────
-const TRIAL_DAYS = 30;
-
-export async function createTrialSubscription(userId: number): Promise {
- const db = await getDb();
- const trialStart = new Date();
- const trialEnd = new Date(trialStart.getTime() + TRIAL_DAYS * 24 * 60 * 60 * 1000);
- await db.insert(subscriptions).values({
- userId,
- plan: "trial",
- status: "trialing",
- trialStartedAt: trialStart,
- trialEndsAt: trialEnd,
- });
- const sub = await getSubscription(userId);
- if (!sub) throw new Error("Failed to create trial subscription");
- return sub;
-}
-
-export async function getSubscription(userId: number): Promise {
- const db = await getDb();
- const rows = await db
- .select()
- .from(subscriptions)
- .where(eq(subscriptions.userId, userId))
- .orderBy(desc(subscriptions.createdAt))
- .limit(1);
- return rows[0] ?? null;
-}
-
-export async function updateSubscription(
- userId: number,
- patch: Partial
-): Promise {
- const db = await getDb();
- await db.update(subscriptions).set(patch).where(eq(subscriptions.userId, userId));
-}
-
-export async function isSubscriptionActive(userId: number): Promise {
- const sub = await getSubscription(userId);
- if (!sub) return false;
- const now = Date.now();
- if (sub.status === "canceled" || sub.status === "expired") return false;
- if (sub.status === "trialing") {
- return sub.trialEndsAt.getTime() > now;
- }
- if (sub.status === "active") {
- if (!sub.currentPeriodEnd) return true;
- return sub.currentPeriodEnd.getTime() > now;
- }
- return false;
-}
-
-// ─── Clinics ─────────────────────────────────────────────────────────────────
-function generateQrToken(): string {
- return crypto.randomBytes(24).toString("hex");
-}
-
-function computeQrExpiry(rotationMinutes: number | null | undefined): Date | null {
- if (!rotationMinutes || rotationMinutes <= 0) return null;
- return new Date(Date.now() + rotationMinutes * 60 * 1000);
-}
-
-export async function getClinics(userId: number): Promise {
- const db = await getDb();
- return db
- .select()
- .from(clinics)
- .where(eq(clinics.userId, userId))
- .orderBy(desc(clinics.createdAt));
-}
-
-export async function getClinicById(id: number): Promise {
- const db = await getDb();
- const rows = await db.select().from(clinics).where(eq(clinics.id, id)).limit(1);
- return rows[0] ?? null;
-}
-
-export async function getClinicByQrToken(token: string): Promise {
- const db = await getDb();
- const rows = await db.select().from(clinics).where(eq(clinics.qrToken, token)).limit(1);
- return rows[0] ?? null;
-}
-
-export async function createClinic(
- userId: number,
- data: Omit
-): Promise<{ insertId: number; qrToken: string }> {
- const db = await getDb();
- const qrToken = generateQrToken();
- const qrTokenExpiresAt = computeQrExpiry(data.qrRotationMinutes ?? 30);
- const [result] = await db.insert(clinics).values({
- ...data,
- userId,
- qrToken,
- qrTokenExpiresAt,
- });
- const insertId = (result as { insertId: number }).insertId;
- return { insertId, qrToken };
-}
-
-export async function updateClinic(
- id: number,
- patch: Partial
-): Promise {
- const db = await getDb();
- await db.update(clinics).set(patch).where(eq(clinics.id, id));
-}
-
-export async function deleteClinic(id: number): Promise {
- const db = await getDb();
- await db.delete(queueEntries).where(eq(queueEntries.clinicId, id));
- await db.delete(analyticsEvents).where(eq(analyticsEvents.clinicId, id));
- await db.delete(clinics).where(eq(clinics.id, id));
-}
-
-export async function rotateQrToken(clinicId: number): Promise<{ qrToken: string; qrTokenExpiresAt: Date | null }> {
- const db = await getDb();
- const clinic = await getClinicById(clinicId);
- if (!clinic) throw new Error("Clinic not found");
- const qrToken = generateQrToken();
- const qrTokenExpiresAt = computeQrExpiry(clinic.qrRotationMinutes);
- await db
- .update(clinics)
- .set({ qrToken, qrTokenExpiresAt })
- .where(eq(clinics.id, clinicId));
- return { qrToken, qrTokenExpiresAt };
-}
-
-export async function ensureFreshQrToken(clinic: Clinic): Promise {
- if (!clinic.qrRotationMinutes || clinic.qrRotationMinutes <= 0) return clinic;
- if (clinic.qrTokenExpiresAt && clinic.qrTokenExpiresAt.getTime() > Date.now()) return clinic;
- await rotateQrToken(clinic.id);
- const refreshed = await getClinicById(clinic.id);
- return refreshed ?? clinic;
-}
-
-// ─── Queue ───────────────────────────────────────────────────────────────────
-type QueueStatus = (typeof queueEntries.$inferSelect)["status"];
-const ACTIVE_STATUSES: QueueStatus[] = ["waiting", "called", "in_consultation"];
-
-export async function getActiveQueue(clinicId: number): Promise {
- const db = await getDb();
- return db
- .select()
- .from(queueEntries)
- .where(
- and(
- eq(queueEntries.clinicId, clinicId),
- inArray(queueEntries.status, ACTIVE_STATUSES)
- )
- )
- .orderBy(queueEntries.position);
-}
-
-export async function getAllQueueEntries(clinicId: number): Promise {
- const db = await getDb();
- return db
- .select()
- .from(queueEntries)
- .where(eq(queueEntries.clinicId, clinicId))
- .orderBy(queueEntries.position);
-}
-
-export async function getQueueEntry(id: number): Promise {
- const db = await getDb();
- const rows = await db.select().from(queueEntries).where(eq(queueEntries.id, id)).limit(1);
- return rows[0] ?? null;
-}
-
-export async function getQueueEntryByToken(token: string): Promise {
- const db = await getDb();
- const rows = await db
- .select()
- .from(queueEntries)
- .where(eq(queueEntries.patientToken, token))
- .orderBy(desc(queueEntries.createdAt))
- .limit(1);
- return rows[0] ?? null;
-}
-
-export async function addToQueue(input: {
- clinicId: number;
- patientName?: string | null;
- patientPhone?: string | null;
- whatsappPhone?: string | null;
- visitReason?:
- | "consultation"
- | "urgence"
- | "certificat_scolaire"
- | "certificat_sportif"
- | "arret_travail"
- | "administratif"
- | "autre"
- | null;
- visitNote?: string | null;
- isPrinted?: boolean;
-}): Promise<{ entry: QueueEntry; ticketNumber: number; patientToken: string }> {
- const db = await getDb();
- const clinic = await getClinicById(input.clinicId);
- if (!clinic) throw new Error("Clinic not found");
- if (!clinic.isQueueOpen) throw new Error("Queue is closed");
-
- const active = await getActiveQueue(input.clinicId);
- if (clinic.maxQueueSize && active.length >= clinic.maxQueueSize) {
- throw new Error("Queue is full");
- }
-
- const ticketNumber = (clinic.currentTicketNumber ?? 0) + 1;
- const patientToken = crypto.randomBytes(24).toString("hex");
- const position = active.length + 1;
- const estimatedWaitMinutes = (clinic.avgConsultationMinutes ?? 15) * (position - 1);
-
- const insertValues: InsertQueueEntry = {
- clinicId: input.clinicId,
- ticketNumber,
- patientToken,
- patientName: input.patientName ?? null,
- patientPhone: input.patientPhone ?? null,
- whatsappPhone: input.whatsappPhone ?? null,
- visitReason: input.visitReason ?? "consultation",
- visitNote: input.visitNote ?? null,
- status: "waiting",
- position,
- estimatedWaitMinutes,
- isPrinted: input.isPrinted ?? false,
- };
-
- const [result] = await db.insert(queueEntries).values(insertValues);
- const insertId = (result as { insertId: number }).insertId;
-
- await db
- .update(clinics)
- .set({ currentTicketNumber: ticketNumber })
- .where(eq(clinics.id, input.clinicId));
-
- const entry = await getQueueEntry(insertId);
- if (!entry) throw new Error("Failed to create queue entry");
- return { entry, ticketNumber, patientToken };
-}
-
-export async function updateQueueEntry(
- id: number,
- patch: Partial
-): Promise {
- const db = await getDb();
- await db.update(queueEntries).set(patch).where(eq(queueEntries.id, id));
-}
-
-export async function reorderQueue(clinicId: number): Promise {
- const db = await getDb();
- const active = await db
- .select()
- .from(queueEntries)
- .where(
- and(
- eq(queueEntries.clinicId, clinicId),
- eq(queueEntries.status, "waiting")
- )
- )
- .orderBy(queueEntries.position, queueEntries.joinedAt);
-
- const clinic = await getClinicById(clinicId);
- const avg = clinic?.avgConsultationMinutes ?? 15;
-
- for (let i = 0; i < active.length; i++) {
- const entry = active[i];
- const newPosition = i + 1;
- const newWait = avg * (newPosition - 1);
- if (entry.position !== newPosition || entry.estimatedWaitMinutes !== newWait) {
- await db
- .update(queueEntries)
- .set({ position: newPosition, estimatedWaitMinutes: newWait })
- .where(eq(queueEntries.id, entry.id));
- }
- }
-
- return getActiveQueue(clinicId);
-}
-
-export async function setQueueOrder(
- clinicId: number,
- orderedIds: number[]
-): Promise {
- const db = await getDb();
- const clinic = await getClinicById(clinicId);
- const avg = clinic?.avgConsultationMinutes ?? 15;
- for (let i = 0; i < orderedIds.length; i++) {
- const id = orderedIds[i];
- const newPosition = i + 1;
- const newWait = avg * (newPosition - 1);
- await db
- .update(queueEntries)
- .set({ position: newPosition, estimatedWaitMinutes: newWait })
- .where(and(eq(queueEntries.id, id), eq(queueEntries.clinicId, clinicId)));
- }
- return getActiveQueue(clinicId);
-}
-
-export async function resetQueue(clinicId: number): Promise {
- const db = await getDb();
- await db
- .update(queueEntries)
- .set({ status: "canceled" })
- .where(
- and(
- eq(queueEntries.clinicId, clinicId),
- inArray(queueEntries.status, ACTIVE_STATUSES)
- )
- );
- await db
- .update(clinics)
- .set({ currentTicketNumber: 0 })
- .where(eq(clinics.id, clinicId));
-}
-
-// ─── Analytics ───────────────────────────────────────────────────────────────
-export async function logAnalyticsEvent(
- data: typeof analyticsEvents.$inferInsert
-): Promise {
- const db = await getDb();
- const now = new Date();
- await db.insert(analyticsEvents).values({
- ...data,
- hourOfDay: data.hourOfDay ?? now.getHours(),
- dayOfWeek: data.dayOfWeek ?? now.getDay(),
- });
-}
-
-export async function getAnalytics(
- userId: number,
- options: { days?: number; clinicId?: number } = {}
-): Promise {
- const db = await getDb();
- const days = options.days ?? 30;
- const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
-
- const userClinics = await getClinics(userId);
- if (userClinics.length === 0) return [];
-
- const clinicIds = options.clinicId
- ? userClinics.filter((c) => c.id === options.clinicId).map((c) => c.id)
- : userClinics.map((c) => c.id);
-
- if (clinicIds.length === 0) return [];
-
- return db
- .select()
- .from(analyticsEvents)
- .where(
- and(
- inArray(analyticsEvents.clinicId, clinicIds),
- gte(analyticsEvents.createdAt, since)
- )
- )
- .orderBy(desc(analyticsEvents.createdAt));
-}
-
-export async function getAnalyticsForClinic(
- clinicId: number,
- days = 30
-): Promise {
- const db = await getDb();
- const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
- return db
- .select()
- .from(analyticsEvents)
- .where(
- and(
- eq(analyticsEvents.clinicId, clinicId),
- gte(analyticsEvents.createdAt, since)
- )
- )
- .orderBy(desc(analyticsEvents.createdAt));
-}
-
-// ─── WhatsApp helpers ────────────────────────────────────────────────────────
-export async function getWaitingEntriesWithPhone(clinicId: number): Promise {
- const db = await getDb();
- return db
- .select()
- .from(queueEntries)
- .where(and(eq(queueEntries.clinicId, clinicId), eq(queueEntries.status, "waiting")))
- .orderBy(queueEntries.position);
-}
-
-/** Masque un numéro de téléphone pour la confidentialité */
-export function maskPhone(phone: string): string {
- const cleaned = phone.replace(/[^\d+]/g, "");
- if (cleaned.length <= 4) return "****";
- const visibleStart = cleaned.slice(0, Math.min(4, cleaned.length - 2));
- const visibleEnd = cleaned.slice(-2);
- const hidden = "*".repeat(Math.max(0, cleaned.length - visibleStart.length - visibleEnd.length));
- return `${visibleStart}${hidden}${visibleEnd}`;
-}
-
-export async function insertWhatsAppLog(
- data: Omit
-): Promise {
- const db = await getDb();
- try {
- await db.insert(whatsappLogs).values(data);
- } catch (err) {
- childLogger("whatsapp-log").warn({ err }, "failed to insert log");
- }
-}
-
-export async function getWhatsAppLogs(
- clinicId: number,
- options: {
- limit?: number;
- offset?: number;
- messageType?: "joined" | "soon" | "called" | "withdrawn" | "test";
- status?: "sent" | "failed";
- } = {}
-) {
- const db = await getDb();
- const { limit = 20, offset = 0, messageType, status } = options;
- const conditions = [eq(whatsappLogs.clinicId, clinicId)];
- if (messageType) conditions.push(eq(whatsappLogs.messageType, messageType));
- if (status) conditions.push(eq(whatsappLogs.status, status));
-
- const [rows, countRows] = await Promise.all([
- db
- .select()
- .from(whatsappLogs)
- .where(and(...conditions))
- .orderBy(desc(whatsappLogs.createdAt))
- .limit(limit)
- .offset(offset),
- db.select({ count: sql`COUNT(*)` }).from(whatsappLogs).where(and(...conditions)),
- ]);
-
- return { logs: rows, total: countRows[0]?.count ?? 0 };
-}
-
-// ─── Consultation history & stats ────────────────────────────────────────────
-export async function getConsultationHistory(
- clinicId: number,
- opts: {
- page?: number;
- perPage?: number;
- dateFrom?: Date;
- dateTo?: Date;
- visitReason?: string;
- } = {}
-): Promise<{ entries: QueueEntry[]; total: number }> {
- const db = await getDb();
- const { page = 1, perPage = 20, dateFrom, dateTo, visitReason } = opts;
- const offset = (page - 1) * perPage;
-
- const conditions = [
- eq(queueEntries.clinicId, clinicId),
- inArray(queueEntries.status, ["done", "absent", "canceled"] as const),
- ];
- if (dateFrom) conditions.push(gte(queueEntries.joinedAt, dateFrom));
- if (dateTo) {
- const endOfDay = new Date(dateTo);
- endOfDay.setHours(23, 59, 59, 999);
- conditions.push(lt(queueEntries.joinedAt, endOfDay));
- }
- if (visitReason) {
- conditions.push(
- eq(
- queueEntries.visitReason,
- visitReason as "consultation" | "urgence" | "certificat_scolaire" | "certificat_sportif" | "arret_travail" | "administratif" | "autre"
- )
- );
- }
-
- const where = and(...conditions);
-
- const entries = await db
- .select()
- .from(queueEntries)
- .where(where!)
- .orderBy(desc(queueEntries.joinedAt))
- .limit(perPage)
- .offset(offset);
-
- const countResult = await db
- .select({ count: sql`count(*)` })
- .from(queueEntries)
- .where(where!);
- const total = Number(countResult[0]?.count ?? 0);
-
- return { entries, total };
-}
-
-export async function getConsultationStats(
- clinicId: number,
- days = 30
-): Promise<{
- totalConsultations: number;
- avgDurationMinutes: number;
- presenceRate: number;
- topReasons: { reason: string; count: number }[];
-}> {
- const db = await getDb();
- const since = new Date();
- since.setDate(since.getDate() - days);
-
- const completed = await db
- .select()
- .from(queueEntries)
- .where(
- and(
- eq(queueEntries.clinicId, clinicId),
- inArray(queueEntries.status, ["done", "absent", "canceled"] as const),
- gte(queueEntries.joinedAt, since)
- )
- );
-
- const doneEntries = completed.filter((e) => e.status === "done");
- const absentEntries = completed.filter((e) => e.status === "absent");
- const totalConsultations = completed.length;
-
- const durations = doneEntries
- .filter((e) => e.consultationStartedAt && e.consultationEndAt)
- .map(
- (e) => (e.consultationEndAt!.getTime() - e.consultationStartedAt!.getTime()) / 60000
- );
- const avgDurationMinutes =
- durations.length > 0
- ? Math.round(durations.reduce((s, d) => s + d, 0) / durations.length)
- : 0;
-
- const presenceRate =
- totalConsultations > 0
- ? Math.round(((totalConsultations - absentEntries.length) / totalConsultations) * 100)
- : 100;
-
- const reasonCounts: Record = {};
- completed.forEach((e) => {
- const r = e.visitReason ?? "consultation";
- reasonCounts[r] = (reasonCounts[r] ?? 0) + 1;
- });
- const topReasons = Object.entries(reasonCounts)
- .map(([reason, count]) => ({ reason, count }))
- .sort((a, b) => b.count - a.count);
-
- return { totalConsultations, avgDurationMinutes, presenceRate, topReasons };
-}
-
-// ─── Admin: users management ─────────────────────────────────────────────────
-export async function listAllUsers(opts: {
- page?: number;
- perPage?: number;
- role?: "user" | "admin";
- search?: string;
-}): Promise<{ users: User[]; total: number }> {
- const db = await getDb();
- const { page = 1, perPage = 20, role, search } = opts;
- const offset = (page - 1) * perPage;
-
- const conditions = [] as ReturnType[];
- if (role) conditions.push(eq(users.role, role));
- if (search) {
- const term = `%${search}%`;
- conditions.push(
- or(like(users.email, term), like(users.name, term)) as ReturnType
- );
- }
- const where = conditions.length > 0 ? and(...conditions) : undefined;
-
- const [rows, countRows] = await Promise.all([
- where
- ? db.select().from(users).where(where).orderBy(desc(users.createdAt)).limit(perPage).offset(offset)
- : db.select().from(users).orderBy(desc(users.createdAt)).limit(perPage).offset(offset),
- where
- ? db.select({ count: sql`COUNT(*)` }).from(users).where(where)
- : db.select({ count: sql`COUNT(*)` }).from(users),
- ]);
-
- return { users: rows, total: Number(countRows[0]?.count ?? 0) };
-}
-
-export async function setUserRole(userId: number, role: "user" | "admin"): Promise {
- const db = await getDb();
- await db.update(users).set({ role }).where(eq(users.id, userId));
-}
-
-export async function setUserDisabled(userId: number, disabled: boolean): Promise {
- const db = await getDb();
- await db.update(users).set({ disabled }).where(eq(users.id, userId));
-}
-
-// ─── Admin: aggregate stats ──────────────────────────────────────────────────
-export async function getAdminOverview(): Promise<{
- totalUsers: number;
- totalAdmins: number;
- totalDisabled: number;
- totalClinics: number;
- totalActiveClinics: number;
- totalQueueEntriesToday: number;
- totalQueueEntriesAllTime: number;
-}> {
- const db = await getDb();
- const startOfDay = new Date();
- startOfDay.setHours(0, 0, 0, 0);
-
- const [
- [usersCount],
- [adminsCount],
- [disabledCount],
- [clinicsCount],
- [activeClinicsCount],
- [queueTodayCount],
- [queueAllTimeCount],
- ] = await Promise.all([
- db.select({ count: sql`COUNT(*)` }).from(users),
- db.select({ count: sql`COUNT(*)` }).from(users).where(eq(users.role, "admin")),
- db.select({ count: sql`COUNT(*)` }).from(users).where(eq(users.disabled, true)),
- db.select({ count: sql`COUNT(*)` }).from(clinics),
- db.select({ count: sql`COUNT(*)` }).from(clinics).where(eq(clinics.isActive, true)),
- db
- .select({ count: sql`COUNT(*)` })
- .from(queueEntries)
- .where(gte(queueEntries.joinedAt, startOfDay)),
- db.select({ count: sql`COUNT(*)` }).from(queueEntries),
- ]);
-
- return {
- totalUsers: Number(usersCount?.count ?? 0),
- totalAdmins: Number(adminsCount?.count ?? 0),
- totalDisabled: Number(disabledCount?.count ?? 0),
- totalClinics: Number(clinicsCount?.count ?? 0),
- totalActiveClinics: Number(activeClinicsCount?.count ?? 0),
- totalQueueEntriesToday: Number(queueTodayCount?.count ?? 0),
- totalQueueEntriesAllTime: Number(queueAllTimeCount?.count ?? 0),
- };
-}
-
-export async function listAllClinicsWithStats(): Promise<
- Array<{
- id: number;
- name: string;
- ownerId: number;
- ownerEmail: string | null;
- ownerName: string | null;
- isActive: boolean;
- isQueueOpen: boolean;
- patientCountToday: number;
- createdAt: Date;
- }>
-> {
- const db = await getDb();
- const startOfDay = new Date();
- startOfDay.setHours(0, 0, 0, 0);
-
- const allClinics = await db.select().from(clinics).orderBy(desc(clinics.createdAt));
- const ownerIds = Array.from(new Set(allClinics.map((c) => c.userId)));
- const owners = ownerIds.length
- ? await db.select().from(users).where(inArray(users.id, ownerIds))
- : [];
- const ownerById = new Map(owners.map((u) => [u.id, u]));
-
- const todayEntries = allClinics.length
- ? await db
- .select({
- clinicId: queueEntries.clinicId,
- count: sql`COUNT(*)`,
- })
- .from(queueEntries)
- .where(
- and(
- inArray(queueEntries.clinicId, allClinics.map((c) => c.id)),
- gte(queueEntries.joinedAt, startOfDay)
- )
- )
- .groupBy(queueEntries.clinicId)
- : [];
- const countByClinic = new Map(todayEntries.map((row) => [row.clinicId, Number(row.count ?? 0)]));
-
- return allClinics.map((c) => {
- const owner = ownerById.get(c.userId);
- return {
- id: c.id,
- name: c.name,
- ownerId: c.userId,
- ownerEmail: owner?.email ?? null,
- ownerName: owner?.name ?? null,
- isActive: c.isActive,
- isQueueOpen: c.isQueueOpen,
- patientCountToday: countByClinic.get(c.id) ?? 0,
- createdAt: c.createdAt,
- };
- });
-}
-
-// ─── Clinic members (multi-practitioner) ─────────────────────────────────────
-export async function listClinicMembers(clinicId: number): Promise<
- Array
-> {
- const db = await getDb();
- const members = await db
- .select()
- .from(clinicMembers)
- .where(eq(clinicMembers.clinicId, clinicId))
- .orderBy(asc(clinicMembers.createdAt));
- if (members.length === 0) return [];
- const userIds = members.map((m) => m.userId);
- const userRows = await db.select().from(users).where(inArray(users.id, userIds));
- const byId = new Map(userRows.map((u) => [u.id, u]));
- return members.map((m) => {
- const u = byId.get(m.userId);
- return { ...m, email: u?.email ?? null, name: u?.name ?? null };
- });
-}
-
-export async function getClinicMember(
- clinicId: number,
- userId: number
-): Promise {
- const db = await getDb();
- const rows = await db
- .select()
- .from(clinicMembers)
- .where(and(eq(clinicMembers.clinicId, clinicId), eq(clinicMembers.userId, userId)))
- .limit(1);
- return rows[0] ?? null;
-}
-
-export async function addClinicMember(data: InsertClinicMember): Promise {
- const db = await getDb();
- const [result] = await db.insert(clinicMembers).values(data);
- const insertId = (result as { insertId: number }).insertId;
- const rows = await db.select().from(clinicMembers).where(eq(clinicMembers.id, insertId)).limit(1);
- if (!rows[0]) throw new Error("Failed to add clinic member");
- return rows[0];
-}
-
-export async function removeClinicMember(clinicId: number, memberId: number): Promise {
- const db = await getDb();
- await db
- .delete(clinicMembers)
- .where(and(eq(clinicMembers.id, memberId), eq(clinicMembers.clinicId, clinicId)));
-}
-
-export async function updateClinicMember(
- memberId: number,
- patch: Partial
-): Promise {
- const db = await getDb();
- await db.update(clinicMembers).set(patch).where(eq(clinicMembers.id, memberId));
-}
-
-// ─── Advanced analytics ──────────────────────────────────────────────────────
-export async function getAdvancedAnalytics(
- userId: number,
- options: { days?: number; clinicId?: number } = {}
-): Promise<{
- byHour: number[];
- byDayOfWeek: number[];
- noShowRate: number;
- totalServed: number;
- totalAbsent: number;
- totalJoined: number;
- busiestDayOfWeek: number;
- peakHour: number;
- avgWaitByDay: Array<{ date: string; avgWaitMinutes: number; count: number }>;
-}> {
- const events = await getAnalytics(userId, options);
-
- const byHour = new Array(24).fill(0);
- const byDayOfWeek = new Array(7).fill(0);
- let totalServed = 0;
- let totalAbsent = 0;
- let totalJoined = 0;
-
- // wait-time aggregation by ISO day (YYYY-MM-DD)
- const waitByDay: Map = new Map();
-
- for (const ev of events) {
- if (typeof ev.hourOfDay === "number") byHour[ev.hourOfDay] += 1;
- if (typeof ev.dayOfWeek === "number") byDayOfWeek[ev.dayOfWeek] += 1;
- if (ev.eventType === "patient_joined") totalJoined += 1;
- if (ev.eventType === "patient_done") totalServed += 1;
- if (ev.eventType === "patient_absent") totalAbsent += 1;
-
- if (typeof ev.waitMinutes === "number" && ev.eventType === "patient_called") {
- const d = ev.createdAt instanceof Date ? ev.createdAt : new Date(ev.createdAt);
- const key = d.toISOString().slice(0, 10);
- const cur = waitByDay.get(key) ?? { total: 0, count: 0 };
- cur.total += ev.waitMinutes;
- cur.count += 1;
- waitByDay.set(key, cur);
- }
- }
-
- const totalCompleted = totalServed + totalAbsent;
- const noShowRate = totalCompleted > 0 ? totalAbsent / totalCompleted : 0;
-
- const peakHour = byHour.indexOf(Math.max(...byHour));
- const busiestDayOfWeek = byDayOfWeek.indexOf(Math.max(...byDayOfWeek));
-
- const avgWaitByDay = Array.from(waitByDay.entries())
- .map(([date, { total, count }]) => ({
- date,
- avgWaitMinutes: count ? Math.round(total / count) : 0,
- count,
- }))
- .sort((a, b) => (a.date < b.date ? -1 : 1));
-
- return {
- byHour,
- byDayOfWeek,
- noShowRate,
- totalServed,
- totalAbsent,
- totalJoined,
- busiestDayOfWeek,
- peakHour,
- avgWaitByDay,
- };
-}
-
-// ─── App Config (intégrations dynamiques) ────────────────────────────────────
-// Cache en mémoire pour éviter une requête DB par appel. Invalidé sur écriture.
-const configCache = new Map();
-let configCacheLoaded = false;
-
-async function loadConfigCache(): Promise {
- const db = await getDb();
- const rows = await db.select().from(appConfig);
- configCache.clear();
- for (const row of rows) {
- configCache.set(row.key, row.value);
- }
- configCacheLoaded = true;
-}
-
-export async function getConfigValue(key: string): Promise {
- if (!configCacheLoaded) {
- try {
- await loadConfigCache();
- } catch (err) {
- childLogger("config").warn({ err, key }, "config cache load failed");
- return null;
- }
- }
- return configCache.get(key) ?? null;
-}
-
-export async function listAllConfig(): Promise {
- const db = await getDb();
- const rows = await db.select().from(appConfig).orderBy(asc(appConfig.category), asc(appConfig.key));
- return rows;
-}
-
-export async function setConfigValue(
- key: string,
- value: string,
- category: string,
- isSecret: boolean,
- description?: string | null
-): Promise {
- const db = await getDb();
- const existing = await db
- .select()
- .from(appConfig)
- .where(eq(appConfig.key, key))
- .limit(1);
- if (existing.length > 0) {
- await db
- .update(appConfig)
- .set({
- value,
- category,
- isSecret: isSecret ? 1 : 0,
- description: description ?? existing[0].description,
- })
- .where(eq(appConfig.key, key));
- } else {
- await db.insert(appConfig).values({
- key,
- value,
- category,
- isSecret: isSecret ? 1 : 0,
- description: description ?? null,
- });
- }
- configCache.set(key, value);
-}
-
-export async function deleteConfigValue(key: string): Promise {
- const db = await getDb();
- await db.delete(appConfig).where(eq(appConfig.key, key));
- configCache.delete(key);
-}
-
-export function invalidateConfigCache(): void {
- configCache.clear();
- configCacheLoaded = false;
-}
diff --git a/server/routers.ts b/server/routers.ts
deleted file mode 100644
index 433881b..0000000
--- a/server/routers.ts
+++ /dev/null
@@ -1,1958 +0,0 @@
-import crypto from "node:crypto";
-import { z } from "zod";
-import { TRPCError } from "@trpc/server";
-import QRCode from "qrcode";
-import { Server as SocketIOServer } from "socket.io";
-import { asc, eq } from "drizzle-orm";
-import {
- router,
- publicProcedure,
- protectedProcedure,
- subscriptionProcedure,
- adminProcedure,
-} from "./_core/trpc.js";
-import {
- getDb,
- getUserByEmail,
- getUserById,
- createUser,
- touchUserLogin,
- createTrialSubscription,
- getSubscription,
- isSubscriptionActive,
- getClinics,
- getClinicById,
- getClinicByQrToken,
- createClinic,
- updateClinic,
- deleteClinic,
- rotateQrToken,
- ensureFreshQrToken,
- getActiveQueue,
- getQueueEntry,
- getQueueEntryByToken,
- setUserResetToken,
- getUserByResetToken,
- updateUserPassword,
- addToQueue,
- updateQueueEntry,
- reorderQueue,
- setQueueOrder,
- resetQueue,
- logAnalyticsEvent,
- getAnalytics,
- getAnalyticsForClinic,
- getConsultationHistory,
- getConsultationStats,
- listAllUsers,
- setUserRole,
- setUserDisabled,
- getAdminOverview,
- listAllClinicsWithStats,
- listClinicMembers,
- getClinicMember,
- addClinicMember,
- removeClinicMember,
- updateClinicMember,
- getAdvancedAnalytics,
- listAllConfig,
- setConfigValue,
- deleteConfigValue,
-} from "./db.js";
-import { whatsappCountryCodes } from "./schema.js";
-import {
- hashPassword,
- verifyPassword,
- createToken,
- setAuthCookie,
- clearAuthCookie,
-} from "./auth.js";
-import { sendMail, buildResetEmail } from "./services/email.js";
-import {
- connectWhatsApp,
- disconnectWhatsApp,
- getWhatsAppStatus,
- getActiveWhatsAppSessionsCount,
- sendWhatsAppMessage,
- buildJoinMessage,
- buildSoonMessage,
- buildCalledMessage,
- buildWithdrawnMessage,
-} from "./services/whatsapp.js";
-import {
- isClinicOpen,
- buildClosedMessage,
- getTodaySchedule,
- getNextOpeningTime,
- formatWeeklySchedule,
- type OpeningHours,
-} from "../shared/openingHours.js";
-import {
- createCheckoutSession,
- createPortalSession,
- isStripeConfigured,
- getStripe,
-} from "./services/stripe.js";
-import { checkPlanLimit, getPlanLimitsForUser } from "./services/planLimits.js";
-import { isSmsConfigured, sendSms } from "./services/sms.js";
-import { generateQueueReport } from "./services/pdfReport.js";
-import { buildSmsMessage } from "../shared/smsTemplates.js";
-import { childLogger } from "./_core/logger.js";
-
-const authLog = childLogger("auth");
-
-// ─── Socket.io accessor ──────────────────────────────────────────────────────
-function getIo(): SocketIOServer | null {
- return (globalThis as unknown as { __socketIo?: SocketIOServer }).__socketIo ?? null;
-}
-
-function emitClinic(clinicId: number, event: string, payload: unknown): void {
- const io = getIo();
- if (!io) return;
- io.to(`clinic:${clinicId}`).emit(event, payload);
- io.to(`display:${clinicId}`).emit(event, payload);
-}
-
-function emitPatient(patientToken: string, event: string, payload: unknown): void {
- const io = getIo();
- if (!io) return;
- io.to(`patient:${patientToken}`).emit(event, payload);
-}
-
-async function broadcastQueueState(clinicId: number): Promise {
- const [clinic, queue] = await Promise.all([
- getClinicById(clinicId),
- getActiveQueue(clinicId),
- ]);
- if (!clinic) return;
- const callingNow = queue.find((e) => e.status === "called") ?? null;
- emitClinic(clinicId, "queue:update", {
- clinic,
- queue,
- callingNow,
- waitingCount: queue.filter((e) => e.status === "waiting").length,
- });
- for (const entry of queue) {
- emitPatient(entry.patientToken, "patient:update", {
- entry,
- position: entry.position,
- estimatedWaitMinutes: entry.estimatedWaitMinutes,
- callingNow,
- waitingCount: queue.filter((e) => e.status === "waiting").length,
- });
- }
-}
-
-function diffMinutes(later: Date, earlier: Date): number {
- return Math.max(0, Math.round((later.getTime() - earlier.getTime()) / 60000));
-}
-
-// ─── Auth router ─────────────────────────────────────────────────────────────
-const authRouter = router({
- register: publicProcedure
- .input(
- z.object({
- email: z.string().email().max(320),
- password: z.string().min(8).max(128),
- name: z.string().min(1).max(128).optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const existing = await getUserByEmail(input.email.toLowerCase());
- if (existing) {
- if (existing.disabled) {
- throw new TRPCError({
- code: "FORBIDDEN",
- message: "Ce compte a été désactivé. Contactez un administrateur.",
- });
- }
- throw new TRPCError({
- code: "CONFLICT",
- message: "Un compte existe déjà avec cet email",
- });
- }
- const passwordHash = await hashPassword(input.password);
- const user = await createUser({
- email: input.email.toLowerCase(),
- passwordHash,
- name: input.name ?? null,
- loginMethod: "password",
- role: "user",
- });
- await createTrialSubscription(user.id);
- const token = createToken(user);
- setAuthCookie(ctx.res, token);
- return {
- success: true,
- user: { id: user.id, email: user.email, name: user.name, role: user.role },
- };
- }),
-
- login: publicProcedure
- .input(
- z.object({
- email: z.string().email().max(320),
- password: z.string().min(1).max(128),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const user = await getUserByEmail(input.email.toLowerCase());
- if (!user) {
- throw new TRPCError({
- code: "UNAUTHORIZED",
- message: "Email ou mot de passe incorrect",
- });
- }
- const ok = await verifyPassword(input.password, user.passwordHash);
- if (!ok) {
- throw new TRPCError({
- code: "UNAUTHORIZED",
- message: "Email ou mot de passe incorrect",
- });
- }
- if (user.disabled) {
- throw new TRPCError({
- code: "FORBIDDEN",
- message: "Ce compte a été désactivé. Contactez un administrateur.",
- });
- }
- await touchUserLogin(user.id);
- const sub = await getSubscription(user.id);
- if (!sub) await createTrialSubscription(user.id);
- const token = createToken(user);
- setAuthCookie(ctx.res, token);
- return {
- success: true,
- user: { id: user.id, email: user.email, name: user.name, role: user.role },
- };
- }),
-
- logout: publicProcedure.mutation(({ ctx }) => {
- clearAuthCookie(ctx.res);
- return { success: true };
- }),
-
- me: publicProcedure.query(async ({ ctx }) => {
- if (!ctx.user) return null;
- const fresh = await getUserById(ctx.user.id);
- if (!fresh) return null;
- return {
- id: fresh.id,
- email: fresh.email,
- name: fresh.name,
- role: fresh.role,
- createdAt: fresh.createdAt,
- lastSignedIn: fresh.lastSignedIn,
- };
- }),
-
- forgotPassword: publicProcedure
- .input(z.object({ email: z.string().email().max(320) }))
- .mutation(async ({ input }) => {
- const user = await getUserByEmail(input.email.toLowerCase());
- if (user) {
- const token = crypto.randomBytes(6).toString("hex");
- const expiry = new Date(Date.now() + 60 * 60 * 1000);
- await setUserResetToken(user.id, token, expiry);
- const baseUrl = process.env.PUBLIC_BASE_URL ?? "";
- const resetUrl = `${baseUrl}/reset-password/${token}`;
- const { subject, html, text } = buildResetEmail(resetUrl);
- try {
- await sendMail({ to: user.email, subject, html, text });
- } catch (err) {
- authLog.error({ err, userId: user.id }, "forgotPassword sendMail failed");
- }
- }
- return { success: true };
- }),
-
- resetPassword: publicProcedure
- .input(
- z.object({
- token: z.string().min(8).max(255),
- newPassword: z.string().min(8).max(128),
- })
- )
- .mutation(async ({ input }) => {
- const user = await getUserByResetToken(input.token);
- if (!user || !user.resetTokenExpiry || user.resetTokenExpiry.getTime() < Date.now()) {
- throw new TRPCError({
- code: "BAD_REQUEST",
- message: "Lien invalide ou expiré",
- });
- }
- const passwordHash = await hashPassword(input.newPassword);
- await updateUserPassword(user.id, passwordHash);
- return { success: true };
- }),
-});
-
-// ─── Clinic router ───────────────────────────────────────────────────────────
-const clinicRouter = router({
- list: protectedProcedure.query(async ({ ctx }) => {
- return getClinics(ctx.user.id);
- }),
-
- getById: protectedProcedure
- .input(z.object({ id: z.number().int().positive() }))
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.id);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return clinic;
- }),
-
- // Public lookup used by display screen and patient pages
- getPublicByToken: publicProcedure
- .input(z.object({ token: z.string().min(8).max(64) }))
- .query(async ({ input }) => {
- const clinic = await getClinicByQrToken(input.token);
- if (!clinic || !clinic.isActive) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Lien expiré ou invalide" });
- }
- return {
- id: clinic.id,
- name: clinic.name,
- address: clinic.address,
- color: clinic.color,
- avgConsultationMinutes: clinic.avgConsultationMinutes,
- isQueueOpen: clinic.isQueueOpen,
- };
- }),
-
- getPublicById: publicProcedure
- .input(z.object({ id: z.number().int().positive() }))
- .query(async ({ input }) => {
- const clinic = await getClinicById(input.id);
- if (!clinic || !clinic.isActive) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return {
- id: clinic.id,
- name: clinic.name,
- color: clinic.color,
- avgConsultationMinutes: clinic.avgConsultationMinutes,
- isQueueOpen: clinic.isQueueOpen,
- };
- }),
-
- create: subscriptionProcedure
- .input(
- z.object({
- name: z.string().min(2).max(255),
- address: z.string().max(500).optional(),
- phone: z.string().max(32).optional(),
- whatsappPhone: z.string().max(32).optional(),
- color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
- avgConsultationMinutes: z.number().int().min(1).max(180).optional(),
- maxQueueSize: z.number().int().min(1).max(500).optional(),
- qrRotationMinutes: z.number().int().min(0).max(1440).optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const limit = await checkPlanLimit(ctx.user.id, "maxClinics");
- if (!limit.ok) {
- throw new TRPCError({ code: "FORBIDDEN", message: limit.reason });
- }
- const result = await createClinic(ctx.user.id, {
- name: input.name,
- address: input.address ?? null,
- phone: input.phone ?? null,
- whatsappPhone: input.whatsappPhone ?? null,
- color: input.color ?? "#10b981",
- avgConsultationMinutes: input.avgConsultationMinutes ?? 15,
- maxQueueSize: input.maxQueueSize ?? 50,
- qrRotationMinutes: input.qrRotationMinutes ?? 30,
- });
- return { success: true, id: result.insertId, qrToken: result.qrToken };
- }),
-
- update: subscriptionProcedure
- .input(
- z.object({
- id: z.number().int().positive(),
- name: z.string().min(2).max(255).optional(),
- address: z.string().max(500).nullable().optional(),
- phone: z.string().max(32).nullable().optional(),
- whatsappPhone: z.string().max(32).nullable().optional(),
- color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
- isActive: z.boolean().optional(),
- avgConsultationMinutes: z.number().int().min(1).max(180).optional(),
- maxQueueSize: z.number().int().min(1).max(500).optional(),
- qrRotationMinutes: z.number().int().min(0).max(1440).optional(),
- autoAbsentMinutes: z.number().int().min(0).max(60).optional(),
- isQueueOpen: z.boolean().optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.id);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
-
- const wasOpen = clinic.isQueueOpen;
- const { id, ...patch } = input;
- await updateClinic(id, patch);
-
- if (typeof input.isQueueOpen === "boolean" && input.isQueueOpen !== wasOpen) {
- await logAnalyticsEvent({
- clinicId: id,
- eventType: input.isQueueOpen ? "queue_opened" : "queue_closed",
- });
- await broadcastQueueState(id);
- }
- return { success: true };
- }),
-
- delete: protectedProcedure
- .input(z.object({ id: z.number().int().positive() }))
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.id);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- await deleteClinic(input.id);
- return { success: true };
- }),
-
- updateSmsSettings: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- smsEnabled: z.boolean(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- if (input.smsEnabled && !(await isSmsConfigured())) {
- throw new TRPCError({
- code: "PRECONDITION_FAILED",
- message: "Twilio n'est pas configuré sur ce serveur.",
- });
- }
- await updateClinic(input.clinicId, { smsEnabled: input.smsEnabled });
- return { success: true, smsEnabled: input.smsEnabled };
- }),
-
- regenerateQr: subscriptionProcedure
- .input(z.object({ id: z.number().int().positive() }))
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.id);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const { qrToken, qrTokenExpiresAt } = await rotateQrToken(input.id);
- emitClinic(input.id, "qr:rotated", { qrToken, qrTokenExpiresAt });
- return { success: true, qrToken, qrTokenExpiresAt };
- }),
-
- qrDataUrl: protectedProcedure
- .input(z.object({ id: z.number().int().positive(), baseUrl: z.string().url().optional() }))
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.id);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const fresh = await ensureFreshQrToken(clinic);
- const base = input.baseUrl ?? "";
- const url = `${base}/q/${fresh.id}/${fresh.qrToken}`;
- const dataUrl = await QRCode.toDataURL(url, {
- width: 512,
- margin: 2,
- color: { dark: "#0f766e", light: "#ffffff" },
- });
- return { url, dataUrl, qrToken: fresh.qrToken, qrTokenExpiresAt: fresh.qrTokenExpiresAt };
- }),
-
- // ─── Members (multi-praticiens) ───────────────────────────────────────────
- listMembers: protectedProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return listClinicMembers(input.clinicId);
- }),
-
- // Public-ish: practitioners visible to display screen (only display name + color)
- listMembersPublic: publicProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || !clinic.isActive) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const members = await listClinicMembers(input.clinicId);
- return members.map((m) => ({
- id: m.id,
- userId: m.userId,
- role: m.role,
- color: m.color,
- displayName: m.displayName ?? m.name ?? null,
- }));
- }),
-
- addMember: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- email: z.string().email().max(320),
- displayName: z.string().min(1).max(128).optional(),
- color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const limit = await checkPlanLimit(ctx.user.id, "multiPractitioner");
- if (!limit.ok) {
- throw new TRPCError({ code: "FORBIDDEN", message: limit.reason });
- }
- const memberUser = await getUserByEmail(input.email.toLowerCase());
- if (!memberUser) {
- throw new TRPCError({
- code: "NOT_FOUND",
- message: "Aucun utilisateur QueueMed avec cet email",
- });
- }
- const existing = await getClinicMember(input.clinicId, memberUser.id);
- if (existing) {
- throw new TRPCError({
- code: "CONFLICT",
- message: "Ce praticien fait déjà partie du cabinet",
- });
- }
- const member = await addClinicMember({
- clinicId: input.clinicId,
- userId: memberUser.id,
- role: "practitioner",
- color: input.color ?? "#10b981",
- displayName: input.displayName ?? memberUser.name ?? null,
- });
- return { success: true, memberId: member.id };
- }),
-
- updateMember: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- memberId: z.number().int().positive(),
- displayName: z.string().min(1).max(128).optional(),
- color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const patch: Record = {};
- if (input.displayName !== undefined) patch.displayName = input.displayName;
- if (input.color !== undefined) patch.color = input.color;
- if (Object.keys(patch).length > 0) {
- await updateClinicMember(input.memberId, patch as Parameters[1]);
- }
- return { success: true };
- }),
-
- removeMember: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- memberId: z.number().int().positive(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- await removeClinicMember(input.clinicId, input.memberId);
- return { success: true };
- }),
-});
-
-// ─── Queue router ────────────────────────────────────────────────────────────
-const queueRouter = router({
- // Public — get queue snapshot for display screen / patient
- getPublic: publicProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input }) => {
- const [clinic, queue] = await Promise.all([
- getClinicById(input.clinicId),
- getActiveQueue(input.clinicId),
- ]);
- if (!clinic || !clinic.isActive) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const callingNow = queue.find((e) => e.status === "called") ?? null;
- return {
- clinic: {
- id: clinic.id,
- name: clinic.name,
- color: clinic.color,
- isQueueOpen: clinic.isQueueOpen,
- avgConsultationMinutes: clinic.avgConsultationMinutes,
- },
- queue: queue.map((e) => ({
- id: e.id,
- ticketNumber: e.ticketNumber,
- status: e.status,
- position: e.position,
- estimatedWaitMinutes: e.estimatedWaitMinutes,
- patientName: e.patientName,
- })),
- callingNow: callingNow
- ? { id: callingNow.id, ticketNumber: callingNow.ticketNumber, patientName: callingNow.patientName, practitionerId: callingNow.practitionerId }
- : null,
- waitingCount: queue.filter((e) => e.status === "waiting").length,
- };
- }),
-
- // Authenticated doctor view — full data
- getForDoctor: protectedProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const queue = await getActiveQueue(input.clinicId);
- return {
- clinic,
- queue,
- callingNow: queue.find((e) => e.status === "called") ?? null,
- waitingCount: queue.filter((e) => e.status === "waiting").length,
- };
- }),
-
- // Patient self-tracking
- // Verify QR token validity (for QR join page)
- verifyQr: publicProcedure
- .input(z.object({ clinicId: z.number().int().positive(), qrToken: z.string().min(8).max(64) }))
- .query(async ({ input }) => {
- let clinic = await getClinicById(input.clinicId);
- if (!clinic || !clinic.isActive) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- // Auto-refresh expired QR token
- if (
- clinic.qrTokenExpiresAt &&
- clinic.qrTokenExpiresAt.getTime() < Date.now() &&
- clinic.qrRotationMinutes &&
- clinic.qrRotationMinutes > 0
- ) {
- await rotateQrToken(clinic.id);
- clinic = (await getClinicById(clinic.id)) ?? clinic;
- }
- if (clinic.qrToken !== input.qrToken) {
- throw new TRPCError({ code: "FORBIDDEN", message: "QR code invalide" });
- }
- const waStatus = getWhatsAppStatus(clinic.id);
- return {
- clinicName: clinic.name,
- isQueueOpen: clinic.isQueueOpen,
- whatsappConnected: waStatus?.connected ?? false,
- };
- }),
-
- getByToken: publicProcedure
- .input(z.object({ patientToken: z.string().min(8).max(64) }))
- .query(async ({ input }) => {
- const entry = await getQueueEntryByToken(input.patientToken);
- if (!entry) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Ticket introuvable" });
- }
- const queue = await getActiveQueue(entry.clinicId);
- const clinic = await getClinicById(entry.clinicId);
- const callingNow = queue.find((e) => e.status === "called") ?? null;
- return {
- entry,
- clinic: clinic
- ? {
- id: clinic.id,
- name: clinic.name,
- color: clinic.color,
- avgConsultationMinutes: clinic.avgConsultationMinutes,
- }
- : null,
- callingNow: callingNow
- ? { ticketNumber: callingNow.ticketNumber, patientName: callingNow.patientName, practitionerId: callingNow.practitionerId }
- : null,
- waitingCount: queue.filter((e) => e.status === "waiting").length,
- };
- }),
-
- getEntryById: publicProcedure
- .input(z.object({ id: z.number().int().positive() }))
- .query(async ({ input }) => {
- const entry = await getQueueEntry(input.id);
- if (!entry) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Ticket introuvable" });
- }
- const clinic = await getClinicById(entry.clinicId);
- return {
- entry,
- clinic: clinic ? { id: clinic.id, name: clinic.name, address: clinic.address } : null,
- };
- }),
-
- // Patient joins queue via QR token
- join: publicProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- qrToken: z.string().min(8).max(64),
- patientName: z.string().min(1).max(128).optional(),
- patientPhone: z.string().min(3).max(32).optional(),
- whatsappPhone: z.string().min(3).max(32).optional(),
- visitReason: z
- .enum([
- "consultation",
- "urgence",
- "certificat_scolaire",
- "certificat_sportif",
- "arret_travail",
- "administratif",
- "autre",
- ])
- .optional(),
- visitNote: z.string().max(200).optional(),
- })
- )
- .mutation(async ({ input }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || !clinic.isActive) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const dailyLimit = await checkPlanLimit(clinic.userId, "maxQueueEntriesPerDay", {
- clinicId: clinic.id,
- });
- if (!dailyLimit.ok) {
- throw new TRPCError({ code: "FORBIDDEN", message: dailyLimit.reason });
- }
- if (clinic.qrToken !== input.qrToken) {
- throw new TRPCError({
- code: "FORBIDDEN",
- message: "QR code expiré, veuillez le rescanner",
- });
- }
- if (
- clinic.qrTokenExpiresAt &&
- clinic.qrTokenExpiresAt.getTime() < Date.now() &&
- clinic.qrRotationMinutes &&
- clinic.qrRotationMinutes > 0
- ) {
- // Auto-refresh expired QR token so patients can always join
- const fresh = await rotateQrToken(clinic.id);
- clinic = (await getClinicById(clinic.id)) ?? clinic;
- }
- if (!clinic.isQueueOpen) {
- throw new TRPCError({ code: "FORBIDDEN", message: "La file est fermée" });
- }
-
- // Vérifier les horaires d'ouverture si configurés
- const openingHours = clinic.openingHours as OpeningHours | null;
- if (openingHours && Object.keys(openingHours).length > 0) {
- if (!isClinicOpen(openingHours)) {
- throw new TRPCError({
- code: "FORBIDDEN",
- message: buildClosedMessage(openingHours, clinic.name),
- });
- }
- }
-
- const { entry, ticketNumber, patientToken } = await addToQueue({
- clinicId: clinic.id,
- patientName: input.patientName,
- patientPhone: input.patientPhone,
- whatsappPhone: input.whatsappPhone,
- visitReason: input.visitReason,
- visitNote: input.visitNote,
- });
-
- const queue = await getActiveQueue(clinic.id);
- await logAnalyticsEvent({
- clinicId: clinic.id,
- eventType: "patient_joined",
- ticketNumber,
- queueSizeAtEvent: queue.length,
- });
-
- await broadcastQueueState(clinic.id);
-
- // Notification WhatsApp "joined" si numéro fourni et session connectée
- if (input.whatsappPhone) {
- const waStatus = getWhatsAppStatus(clinic.id);
- if (waStatus.status === "connected") {
- const customTemplates = {
- joined: clinic.whatsappTemplateJoined,
- soon: clinic.whatsappTemplateSoon,
- called: clinic.whatsappTemplateCalled,
- withdrawn: clinic.whatsappTemplateWithdrawn,
- };
- const msg = buildJoinMessage(
- clinic.name,
- ticketNumber,
- entry.position,
- entry.estimatedWaitMinutes ?? 0,
- customTemplates
- );
- sendWhatsAppMessage(clinic.id, input.whatsappPhone, msg)
- .then(() => updateQueueEntry(entry.id, { whatsappSentJoined: true }))
- .catch(() => {
- /* silent */
- });
- }
- }
-
- return {
- success: true,
- entryId: entry.id,
- ticketNumber,
- patientToken,
- position: entry.position,
- estimatedWaitMinutes: entry.estimatedWaitMinutes,
- };
- }),
-
- // Doctor prints a ticket for a patient without smartphone
- joinPrinted: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- patientName: z.string().min(1).max(128).optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- if (!clinic.isQueueOpen) {
- throw new TRPCError({ code: "FORBIDDEN", message: "La file est fermée" });
- }
-
- const { entry, ticketNumber, patientToken } = await addToQueue({
- clinicId: clinic.id,
- patientName: input.patientName,
- isPrinted: true,
- });
-
- const queue = await getActiveQueue(clinic.id);
- await logAnalyticsEvent({
- clinicId: clinic.id,
- eventType: "patient_joined",
- ticketNumber,
- queueSizeAtEvent: queue.length,
- metadata: { printed: true },
- });
-
- await broadcastQueueState(clinic.id);
- return {
- success: true,
- entryId: entry.id,
- ticketNumber,
- patientToken,
- position: entry.position,
- estimatedWaitMinutes: entry.estimatedWaitMinutes,
- };
- }),
-
- callNext: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- practitionerId: z.number().int().positive().optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
-
- const queue = await getActiveQueue(input.clinicId);
- const previouslyCalled = queue.filter((e) => e.status === "called");
- for (const prev of previouslyCalled) {
- await updateQueueEntry(prev.id, {
- status: "in_consultation",
- consultationStartAt: new Date(),
- });
- }
-
- const next = queue.find((e) => e.status === "waiting");
- if (!next) {
- await broadcastQueueState(input.clinicId);
- return { success: true, called: null };
- }
-
- const now = new Date();
- await updateQueueEntry(next.id, {
- status: "called",
- calledAt: now,
- notificationSent: true,
- ...(input.practitionerId ? { practitionerId: input.practitionerId } : {}),
- });
-
- const waitMinutes = diffMinutes(now, next.joinedAt);
- await logAnalyticsEvent({
- clinicId: clinic.id,
- eventType: "patient_called",
- ticketNumber: next.ticketNumber,
- waitMinutes,
- queueSizeAtEvent: queue.length,
- });
-
- await reorderQueue(clinic.id);
- await broadcastQueueState(clinic.id);
-
- emitPatient(next.patientToken, "patient:called", {
- ticketNumber: next.ticketNumber,
- clinicId: clinic.id,
- });
-
- const upcoming = (await getActiveQueue(clinic.id)).find((e) => e.status === "waiting");
- if (upcoming) {
- emitPatient(upcoming.patientToken, "patient:approaching", {
- ticketNumber: upcoming.ticketNumber,
- });
- }
-
- // Notifications WhatsApp pour le patient appelé + le suivant
- const waStatus = getWhatsAppStatus(clinic.id);
- if (waStatus.status === "connected") {
- const customTemplates = {
- joined: clinic.whatsappTemplateJoined,
- soon: clinic.whatsappTemplateSoon,
- called: clinic.whatsappTemplateCalled,
- withdrawn: clinic.whatsappTemplateWithdrawn,
- };
- if (next.whatsappPhone && !next.whatsappSentCalled) {
- const msg = buildCalledMessage(clinic.name, next.ticketNumber, customTemplates);
- sendWhatsAppMessage(clinic.id, next.whatsappPhone, msg)
- .then(() => updateQueueEntry(next.id, { whatsappSentCalled: true }))
- .catch(() => {
- /* silent */
- });
- }
- if (upcoming && upcoming.whatsappPhone && !upcoming.whatsappSentSoon) {
- const minutesLeft = clinic.avgConsultationMinutes ?? 15;
- const msg = buildSoonMessage(
- clinic.name,
- upcoming.ticketNumber,
- minutesLeft,
- customTemplates
- );
- sendWhatsAppMessage(clinic.id, upcoming.whatsappPhone, msg)
- .then(() => updateQueueEntry(upcoming.id, { whatsappSentSoon: true }))
- .catch(() => {
- /* silent */
- });
- }
- }
-
- return {
- success: true,
- called: { id: next.id, ticketNumber: next.ticketNumber, patientName: next.patientName },
- };
- }),
-
- callSpecific: subscriptionProcedure
- .input(
- z.object({
- entryId: z.number().int().positive(),
- practitionerId: z.number().int().positive().optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const entry = await getQueueEntry(input.entryId);
- if (!entry) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Patient introuvable" });
- }
- const clinic = await getClinicById(entry.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
-
- const queue = await getActiveQueue(entry.clinicId);
- for (const prev of queue.filter((e) => e.status === "called" && e.id !== entry.id)) {
- await updateQueueEntry(prev.id, {
- status: "in_consultation",
- consultationStartAt: new Date(),
- });
- }
-
- const now = new Date();
- await updateQueueEntry(entry.id, {
- status: "called",
- calledAt: now,
- notificationSent: true,
- ...(input.practitionerId ? { practitionerId: input.practitionerId } : {}),
- });
-
- const waitMinutes = diffMinutes(now, entry.joinedAt);
- await logAnalyticsEvent({
- clinicId: entry.clinicId,
- eventType: "patient_called",
- ticketNumber: entry.ticketNumber,
- waitMinutes,
- queueSizeAtEvent: queue.length,
- });
-
- await reorderQueue(entry.clinicId);
- await broadcastQueueState(entry.clinicId);
-
- emitPatient(entry.patientToken, "patient:called", {
- ticketNumber: entry.ticketNumber,
- clinicId: entry.clinicId,
- });
-
- return { success: true };
- }),
-
- markAbsent: subscriptionProcedure
- .input(z.object({ entryId: z.number().int().positive() }))
- .mutation(async ({ input, ctx }) => {
- const entry = await getQueueEntry(input.entryId);
- if (!entry) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Patient introuvable" });
- }
- const clinic = await getClinicById(entry.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
-
- await updateQueueEntry(entry.id, { status: "absent" });
- await logAnalyticsEvent({
- clinicId: entry.clinicId,
- eventType: "patient_absent",
- ticketNumber: entry.ticketNumber,
- });
-
- await reorderQueue(entry.clinicId);
- await broadcastQueueState(entry.clinicId);
- emitPatient(entry.patientToken, "patient:absent", { entryId: entry.id });
-
- return { success: true };
- }),
-
- markDone: subscriptionProcedure
- .input(z.object({ entryId: z.number().int().positive() }))
- .mutation(async ({ input, ctx }) => {
- const entry = await getQueueEntry(input.entryId);
- if (!entry) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Patient introuvable" });
- }
- const clinic = await getClinicById(entry.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
-
- const now = new Date();
- const startedAt = entry.consultationStartAt ?? entry.calledAt ?? now;
- const consultationMinutes = diffMinutes(now, startedAt);
-
- await updateQueueEntry(entry.id, {
- status: "done",
- consultationEndAt: now,
- consultationStartAt: entry.consultationStartAt ?? entry.calledAt,
- });
-
- const waitMinutes = entry.calledAt ? diffMinutes(entry.calledAt, entry.joinedAt) : null;
- await logAnalyticsEvent({
- clinicId: entry.clinicId,
- eventType: "patient_done",
- ticketNumber: entry.ticketNumber,
- waitMinutes,
- consultationMinutes,
- });
-
- await reorderQueue(entry.clinicId);
- await broadcastQueueState(entry.clinicId);
- emitPatient(entry.patientToken, "patient:done", { entryId: entry.id });
-
- return { success: true };
- }),
-
- cancel: publicProcedure
- .input(z.object({ patientToken: z.string().min(8).max(64) }))
- .mutation(async ({ input }) => {
- const entry = await getQueueEntryByToken(input.patientToken);
- if (!entry) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Ticket introuvable" });
- }
- if (entry.status !== "waiting" && entry.status !== "called") {
- return { success: true };
- }
- await updateQueueEntry(entry.id, { status: "canceled" });
- await reorderQueue(entry.clinicId);
- await broadcastQueueState(entry.clinicId);
-
- // Notification WhatsApp "withdrawn" si numéro + session connectée
- const clinic = await getClinicById(entry.clinicId);
- if (clinic && entry.whatsappPhone) {
- const waStatus = getWhatsAppStatus(entry.clinicId);
- if (waStatus.status === "connected") {
- const customTemplates = {
- joined: clinic.whatsappTemplateJoined,
- soon: clinic.whatsappTemplateSoon,
- called: clinic.whatsappTemplateCalled,
- withdrawn: clinic.whatsappTemplateWithdrawn,
- };
- const msg = buildWithdrawnMessage(clinic.name, entry.ticketNumber, customTemplates);
- sendWhatsAppMessage(entry.clinicId, entry.whatsappPhone, msg).catch(() => {
- /* silent */
- });
- }
- }
-
- return { success: true };
- }),
-
- reorder: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- orderedEntryIds: z.array(z.number().int().positive()).min(1),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- await setQueueOrder(input.clinicId, input.orderedEntryIds);
- await broadcastQueueState(input.clinicId);
- return { success: true };
- }),
-
- reset: subscriptionProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- await resetQueue(input.clinicId);
- await broadcastQueueState(input.clinicId);
- return { success: true };
- }),
-});
-
-// ─── Analytics router ────────────────────────────────────────────────────────
-const analyticsRouter = router({
- getAll: protectedProcedure
- .input(
- z.object({
- days: z.number().int().min(1).max(365).optional(),
- clinicId: z.number().int().positive().optional(),
- })
- )
- .query(async ({ input, ctx }) => {
- return getAnalytics(ctx.user.id, {
- days: input.days,
- clinicId: input.clinicId,
- });
- }),
-
- summary: protectedProcedure
- .input(
- z.object({
- days: z.number().int().min(1).max(365).default(30),
- clinicId: z.number().int().positive().optional(),
- })
- )
- .query(async ({ input, ctx }) => {
- const events = await getAnalytics(ctx.user.id, {
- days: input.days,
- clinicId: input.clinicId,
- });
-
- const byHour = new Array(24).fill(0);
- const byDay = new Array(7).fill(0);
- let totalWait = 0;
- let waitCount = 0;
- let totalConsult = 0;
- let consultCount = 0;
- let totalServed = 0;
- let totalAbsent = 0;
- let totalJoined = 0;
-
- for (const ev of events) {
- if (typeof ev.hourOfDay === "number") byHour[ev.hourOfDay] += 1;
- if (typeof ev.dayOfWeek === "number") byDay[ev.dayOfWeek] += 1;
- if (ev.eventType === "patient_joined") totalJoined += 1;
- if (ev.eventType === "patient_done") totalServed += 1;
- if (ev.eventType === "patient_absent") totalAbsent += 1;
- if (typeof ev.waitMinutes === "number") {
- totalWait += ev.waitMinutes;
- waitCount += 1;
- }
- if (typeof ev.consultationMinutes === "number") {
- totalConsult += ev.consultationMinutes;
- consultCount += 1;
- }
- }
-
- const peakHour = byHour.indexOf(Math.max(...byHour));
- const peakDay = byDay.indexOf(Math.max(...byDay));
- const recommendations: string[] = [];
- if (waitCount > 0 && totalWait / waitCount > 30) {
- recommendations.push(
- "Le temps d'attente moyen dépasse 30 minutes — augmentez la cadence ou ouvrez la file plus tôt."
- );
- }
- if (totalJoined > 0 && totalAbsent / totalJoined > 0.15) {
- recommendations.push(
- "Plus de 15% d'absences — pensez à activer les notifications SMS pour les patients."
- );
- }
- if (Math.max(...byHour) > 0) {
- recommendations.push(
- `Pic d'affluence à ${peakHour}h — prévoyez du renfort ou ouvrez la file 30 min avant.`
- );
- }
-
- return {
- totalJoined,
- totalServed,
- totalAbsent,
- avgWaitMinutes: waitCount ? Math.round(totalWait / waitCount) : 0,
- avgConsultationMinutes: consultCount ? Math.round(totalConsult / consultCount) : 0,
- byHour,
- byDay,
- peakHour,
- peakDay,
- recommendations,
- };
- }),
-
- getAdvanced: protectedProcedure
- .input(
- z.object({
- days: z.number().int().min(1).max(365).default(30),
- clinicId: z.number().int().positive().optional(),
- })
- )
- .query(async ({ input, ctx }) => {
- return getAdvancedAnalytics(ctx.user.id, {
- days: input.days,
- clinicId: input.clinicId,
- });
- }),
-
- exportCsv: protectedProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- days: z.number().int().min(1).max(365).default(90),
- })
- )
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const events = await getAnalyticsForClinic(input.clinicId, input.days);
-
- const header = [
- "createdAt",
- "eventType",
- "ticketNumber",
- "waitMinutes",
- "consultationMinutes",
- "queueSizeAtEvent",
- "hourOfDay",
- "dayOfWeek",
- ];
-
- const escape = (v: unknown): string => {
- if (v === null || v === undefined) return "";
- const s = String(v);
- if (/[",\n]/.test(s)) return `"${s.replace(/"/g, '""')}"`;
- return s;
- };
-
- const rows = events.map((e) =>
- [
- e.createdAt instanceof Date ? e.createdAt.toISOString() : String(e.createdAt),
- e.eventType,
- e.ticketNumber,
- e.waitMinutes,
- e.consultationMinutes,
- e.queueSizeAtEvent,
- e.hourOfDay,
- e.dayOfWeek,
- ]
- .map(escape)
- .join(",")
- );
-
- const csv = [header.join(","), ...rows].join("\n");
- const filename = `queuemed_${clinic.name.replace(/[^a-z0-9]+/gi, "_")}_${new Date()
- .toISOString()
- .slice(0, 10)}.csv`;
- return { csv, filename };
- }),
-
- exportPdf: protectedProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- days: z.number().int().min(1).max(365).default(30),
- })
- )
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- try {
- const buf = await generateQueueReport(input.clinicId, { days: input.days });
- const filename = `queuemed_${clinic.name.replace(/[^a-z0-9]+/gi, "_")}_${new Date()
- .toISOString()
- .slice(0, 10)}.pdf`;
- return {
- base64: buf.toString("base64"),
- filename,
- };
- } catch (err) {
- const message = err instanceof Error ? err.message : "PDF generation failed";
- throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message });
- }
- }),
-});
-
-// ─── Notification router (SMS Twilio) ────────────────────────────────────────
-const notificationRouter = router({
- smsStatus: protectedProcedure.query(async () => {
- return { configured: await isSmsConfigured() };
- }),
-
- sendSms: subscriptionProcedure
- .input(
- z.object({
- entryId: z.number().int().positive(),
- message: z.string().max(500).optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- if (!(await isSmsConfigured())) {
- throw new TRPCError({
- code: "PRECONDITION_FAILED",
- message: "Twilio n'est pas configuré sur ce serveur.",
- });
- }
- const entry = await getQueueEntry(input.entryId);
- if (!entry) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Patient introuvable" });
- }
- const clinic = await getClinicById(entry.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- if (!clinic.smsEnabled) {
- throw new TRPCError({
- code: "FORBIDDEN",
- message: "Les notifications SMS ne sont pas activées pour ce cabinet.",
- });
- }
- const phone = entry.patientPhone ?? entry.whatsappPhone ?? null;
- if (!phone) {
- throw new TRPCError({
- code: "BAD_REQUEST",
- message: "Aucun numéro de téléphone enregistré pour ce patient.",
- });
- }
-
- const message =
- input.message ??
- buildSmsMessage("called", {
- nom: entry.patientName ?? "",
- ticket: entry.ticketNumber,
- position: entry.position,
- attente: entry.estimatedWaitMinutes ?? 0,
- cabinet: clinic.name,
- });
-
- return sendSms(phone, message);
- }),
-});
-
-// ─── Subscription router ─────────────────────────────────────────────────────
-const subscriptionRouter = router({
- get: protectedProcedure.query(async ({ ctx }) => {
- return getSubscription(ctx.user.id);
- }),
-
- check: protectedProcedure.query(async ({ ctx }) => {
- const sub = await getSubscription(ctx.user.id);
- const active = await isSubscriptionActive(ctx.user.id);
- let daysRemaining = 0;
- if (sub) {
- if (sub.status === "trialing" && sub.trialEndsAt) {
- daysRemaining = Math.max(
- 0,
- Math.ceil((sub.trialEndsAt.getTime() - Date.now()) / (24 * 60 * 60 * 1000))
- );
- } else if (sub.status === "active" && sub.currentPeriodEnd) {
- daysRemaining = Math.max(
- 0,
- Math.ceil((sub.currentPeriodEnd.getTime() - Date.now()) / (24 * 60 * 60 * 1000))
- );
- }
- }
- return {
- active,
- plan: sub?.plan ?? null,
- status: sub?.status ?? null,
- trialEndsAt: sub?.trialEndsAt ?? null,
- currentPeriodEnd: sub?.currentPeriodEnd ?? null,
- daysRemaining,
- };
- }),
-
- getCurrentPlan: protectedProcedure.query(async ({ ctx }) => {
- const sub = await getSubscription(ctx.user.id);
- const { plan, limits } = await getPlanLimitsForUser(ctx.user.id);
- const stripeReady = await isStripeConfigured();
- return {
- plan,
- status: sub?.status ?? null,
- trialEndsAt: sub?.trialEndsAt ?? null,
- currentPeriodEnd: sub?.currentPeriodEnd ?? null,
- hasStripeCustomer: Boolean(sub?.stripeCustomerId),
- hasActiveSubscription: Boolean(sub?.stripeSubscriptionId),
- stripeConfigured: stripeReady,
- limits: {
- maxClinics:
- limits.maxClinics === Infinity ? null : limits.maxClinics,
- maxQueueEntriesPerDay:
- limits.maxQueueEntriesPerDay === Infinity
- ? null
- : limits.maxQueueEntriesPerDay,
- multiPractitioner: limits.multiPractitioner,
- analyticsExport: limits.analyticsExport,
- },
- };
- }),
-
- createCheckoutSession: protectedProcedure
- .input(z.object({ priceId: z.string().min(1).max(255) }))
- .mutation(async ({ input, ctx }) => {
- if (!isStripeConfigured()) {
- throw new TRPCError({
- code: "PRECONDITION_FAILED",
- message: "Le paiement n'est pas encore configuré. Contactez l'administrateur.",
- });
- }
- try {
- const { url } = await createCheckoutSession(ctx.user.id, input.priceId);
- return { url };
- } catch (err) {
- const message = err instanceof Error ? err.message : "Stripe Checkout failed";
- throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message });
- }
- }),
-
- createPortalSession: protectedProcedure.mutation(async ({ ctx }) => {
- if (!isStripeConfigured()) {
- throw new TRPCError({
- code: "PRECONDITION_FAILED",
- message: "Le paiement n'est pas encore configuré. Contactez l'administrateur.",
- });
- }
- try {
- const { url } = await createPortalSession(ctx.user.id);
- return { url };
- } catch (err) {
- const message = err instanceof Error ? err.message : "Stripe Portal failed";
- throw new TRPCError({ code: "BAD_REQUEST", message });
- }
- }),
-});
-
-// ─── WhatsApp router ─────────────────────────────────────────────────────────
-const whatsappRouter = router({
- status: subscriptionProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return getWhatsAppStatus(input.clinicId);
- }),
-
- connect: subscriptionProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- await connectWhatsApp(input.clinicId);
- // Petit délai pour laisser le QR se générer
- await new Promise((r) => setTimeout(r, 2000));
- return getWhatsAppStatus(input.clinicId);
- }),
-
- disconnect: subscriptionProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- await disconnectWhatsApp(input.clinicId);
- return { success: true };
- }),
-
- sendTest: subscriptionProcedure
- .input(z.object({ clinicId: z.number().int().positive(), phone: z.string().min(3).max(32) }))
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return sendWhatsAppMessage(
- input.clinicId,
- input.phone,
- `✅ *Test QueueMed*\n\nVotre connexion WhatsApp fonctionne correctement pour le cabinet *${clinic.name}*.`
- );
- }),
-
- // Public — list enabled country codes for patient form
- listCountryCodes: publicProcedure.query(async () => {
- const db = await getDb();
- return db
- .select()
- .from(whatsappCountryCodes)
- .where(eq(whatsappCountryCodes.enabled, true))
- .orderBy(asc(whatsappCountryCodes.sortOrder), asc(whatsappCountryCodes.nameFr));
- }),
-
- // Admin — list all country codes
- listAllCountryCodes: protectedProcedure.query(async ({ ctx }) => {
- if (ctx.user.role !== "admin") {
- throw new TRPCError({ code: "FORBIDDEN", message: "Accès réservé aux administrateurs" });
- }
- const db = await getDb();
- return db
- .select()
- .from(whatsappCountryCodes)
- .orderBy(asc(whatsappCountryCodes.sortOrder), asc(whatsappCountryCodes.nameFr));
- }),
-
- toggleCountryCode: protectedProcedure
- .input(z.object({ code: z.string().min(2).max(4), enabled: z.boolean() }))
- .mutation(async ({ input, ctx }) => {
- if (ctx.user.role !== "admin") {
- throw new TRPCError({ code: "FORBIDDEN" });
- }
- const db = await getDb();
- await db
- .update(whatsappCountryCodes)
- .set({ enabled: input.enabled })
- .where(eq(whatsappCountryCodes.code, input.code));
- return { success: true };
- }),
-
- bulkToggleCountryCodes: protectedProcedure
- .input(z.object({ codes: z.array(z.string()), enabled: z.boolean() }))
- .mutation(async ({ input, ctx }) => {
- if (ctx.user.role !== "admin") {
- throw new TRPCError({ code: "FORBIDDEN" });
- }
- const db = await getDb();
- for (const code of input.codes) {
- await db
- .update(whatsappCountryCodes)
- .set({ enabled: input.enabled })
- .where(eq(whatsappCountryCodes.code, code));
- }
- return { success: true, count: input.codes.length };
- }),
-});
-
-// ─── Clinic enriched settings router ─────────────────────────────────────────
-const clinicSettingsRouter = router({
- get: subscriptionProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return {
- id: clinic.id,
- name: clinic.name,
- address: clinic.address,
- phone: clinic.phone,
- whatsappPhone: clinic.whatsappPhone,
- color: clinic.color,
- avgConsultationMinutes: clinic.avgConsultationMinutes,
- maxQueueSize: clinic.maxQueueSize,
- qrRotationMinutes: clinic.qrRotationMinutes,
- autoAbsentMinutes: clinic.autoAbsentMinutes ?? 0,
- welcomeMessage: clinic.welcomeMessage ?? "",
- openingHours: clinic.openingHours as Record<
- string,
- { open: string; close: string; closed: boolean }
- > | null,
- patientLanguage: clinic.patientLanguage ?? "fr",
- whatsappTemplateJoined: clinic.whatsappTemplateJoined ?? null,
- whatsappTemplateSoon: clinic.whatsappTemplateSoon ?? null,
- whatsappTemplateCalled: clinic.whatsappTemplateCalled ?? null,
- whatsappTemplateWithdrawn: clinic.whatsappTemplateWithdrawn ?? null,
- smsEnabled: clinic.smsEnabled ?? false,
- };
- }),
-
- update: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- welcomeMessage: z.string().max(500).optional(),
- openingHours: z
- .record(
- z.string(),
- z.object({ open: z.string(), close: z.string(), closed: z.boolean() })
- )
- .optional(),
- patientLanguage: z.enum(["fr", "en", "ar", "pt", "es"]).optional(),
- autoAbsentMinutes: z.number().int().min(0).max(60).optional(),
- avgConsultationMinutes: z.number().int().min(1).max(180).optional(),
- maxQueueSize: z.number().int().min(1).max(500).optional(),
- whatsappPhone: z.string().max(32).nullable().optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const { clinicId, ...patch } = input;
- const filtered = Object.fromEntries(
- Object.entries(patch).filter(([, v]) => v !== undefined)
- );
- if (Object.keys(filtered).length > 0) {
- await updateClinic(clinicId, filtered as Parameters[1]);
- }
- return { success: true };
- }),
-
- getTemplates: subscriptionProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return {
- joined: clinic.whatsappTemplateJoined ?? null,
- soon: clinic.whatsappTemplateSoon ?? null,
- called: clinic.whatsappTemplateCalled ?? null,
- withdrawn: clinic.whatsappTemplateWithdrawn ?? null,
- };
- }),
-
- updateTemplates: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- joined: z.string().max(1000).nullable().optional(),
- soon: z.string().max(1000).nullable().optional(),
- called: z.string().max(1000).nullable().optional(),
- withdrawn: z.string().max(1000).nullable().optional(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const updateData: Record = {};
- if (input.joined !== undefined) updateData.whatsappTemplateJoined = input.joined;
- if (input.soon !== undefined) updateData.whatsappTemplateSoon = input.soon;
- if (input.called !== undefined) updateData.whatsappTemplateCalled = input.called;
- if (input.withdrawn !== undefined) updateData.whatsappTemplateWithdrawn = input.withdrawn;
- if (Object.keys(updateData).length > 0) {
- await updateClinic(input.clinicId, updateData as Parameters[1]);
- }
- return { success: true };
- }),
-
- // État d'ouverture du cabinet selon les horaires configurés
- openingStatus: publicProcedure
- .input(z.object({ clinicId: z.number().int().positive() }))
- .query(async ({ input }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- const openingHours = clinic.openingHours as OpeningHours | null;
- const hasHours = openingHours && Object.keys(openingHours).length > 0;
- if (!hasHours) {
- return {
- isOpen: true,
- hasHours: false,
- todaySchedule: null,
- nextOpening: null,
- weeklySchedule: [],
- clinicName: clinic.name,
- };
- }
- const isOpen = isClinicOpen(openingHours);
- const { dayKey, schedule } = getTodaySchedule(openingHours);
- const nextOpening = isOpen ? null : getNextOpeningTime(openingHours);
- const weeklySchedule = formatWeeklySchedule(openingHours);
- return {
- isOpen,
- hasHours: true,
- todaySchedule: schedule
- ? { dayKey, open: schedule.open, close: schedule.close, closed: schedule.closed }
- : null,
- nextOpening,
- weeklySchedule,
- clinicName: clinic.name,
- };
- }),
-
- toggleSms: protectedProcedure
- .input(z.object({ clinicId: z.number().int().positive(), enabled: z.boolean() }))
- .mutation(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- await updateClinic(input.clinicId, { smsEnabled: input.enabled });
- return { success: true, smsEnabled: input.enabled };
- }),
-
-});
-
-// ─── Consultation history router ─────────────────────────────────────────────
-const historyRouter = router({
- list: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- page: z.number().int().min(1).optional(),
- perPage: z.number().int().min(5).max(100).optional(),
- dateFrom: z.string().optional(),
- dateTo: z.string().optional(),
- visitReason: z.string().optional(),
- })
- )
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return getConsultationHistory(input.clinicId, {
- page: input.page,
- perPage: input.perPage,
- dateFrom: input.dateFrom ? new Date(input.dateFrom) : undefined,
- dateTo: input.dateTo ? new Date(input.dateTo) : undefined,
- visitReason: input.visitReason,
- });
- }),
-
- stats: subscriptionProcedure
- .input(
- z.object({
- clinicId: z.number().int().positive(),
- days: z.number().int().min(1).max(365).optional(),
- })
- )
- .query(async ({ input, ctx }) => {
- const clinic = await getClinicById(input.clinicId);
- if (!clinic || clinic.userId !== ctx.user.id) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Cabinet introuvable" });
- }
- return getConsultationStats(input.clinicId, input.days ?? 30);
- }),
-});
-
-// ─── Admin router ────────────────────────────────────────────────────────────
-const adminRouter = router({
- listUsers: adminProcedure
- .input(
- z.object({
- page: z.number().int().min(1).default(1),
- perPage: z.number().int().min(5).max(100).default(20),
- role: z.enum(["user", "admin"]).optional(),
- search: z.string().max(120).optional(),
- })
- )
- .query(async ({ input }) => {
- const { users: rows, total } = await listAllUsers({
- page: input.page,
- perPage: input.perPage,
- role: input.role,
- search: input.search,
- });
- return {
- users: rows.map((u) => ({
- id: u.id,
- email: u.email,
- name: u.name,
- role: u.role,
- disabled: u.disabled,
- createdAt: u.createdAt,
- lastSignedIn: u.lastSignedIn,
- })),
- total,
- page: input.page,
- perPage: input.perPage,
- };
- }),
-
- updateUserRole: adminProcedure
- .input(
- z.object({
- userId: z.number().int().positive(),
- role: z.enum(["user", "admin"]),
- })
- )
- .mutation(async ({ input, ctx }) => {
- if (input.userId === ctx.user.id && input.role !== "admin") {
- throw new TRPCError({
- code: "BAD_REQUEST",
- message: "Vous ne pouvez pas retirer votre propre rôle administrateur",
- });
- }
- const target = await getUserById(input.userId);
- if (!target) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Utilisateur introuvable" });
- }
- await setUserRole(input.userId, input.role);
- return { success: true };
- }),
-
- disableUser: adminProcedure
- .input(
- z.object({
- userId: z.number().int().positive(),
- disabled: z.boolean(),
- })
- )
- .mutation(async ({ input, ctx }) => {
- if (input.userId === ctx.user.id && input.disabled) {
- throw new TRPCError({
- code: "BAD_REQUEST",
- message: "Vous ne pouvez pas désactiver votre propre compte",
- });
- }
- const target = await getUserById(input.userId);
- if (!target) {
- throw new TRPCError({ code: "NOT_FOUND", message: "Utilisateur introuvable" });
- }
- await setUserDisabled(input.userId, input.disabled);
- return { success: true };
- }),
-
- listAllClinics: adminProcedure.query(async () => {
- return listAllClinicsWithStats();
- }),
-
- getOverview: adminProcedure.query(async () => {
- const overview = await getAdminOverview();
- return {
- ...overview,
- activeWhatsAppSessions: getActiveWhatsAppSessionsCount(),
- };
- }),
-
- // --- Admin Config (integrations & secrets) ---
- listConfig: adminProcedure
- .query(async () => {
- const rows = await listAllConfig();
- return rows.map((r) => ({
- key: r.key,
- value: r.isSecret ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : r.value,
- isSecret: Boolean(r.isSecret),
- category: r.category,
- description: r.description,
- updatedAt: r.updatedAt,
- }));
- }),
-
- setConfig: adminProcedure
- .input(
- z.object({
- key: z.string().max(100),
- value: z.string(),
- isSecret: z.boolean().default(false),
- category: z.string().max(50),
- description: z.string().max(255).optional(),
- })
- )
- .mutation(async ({ input }) => {
- await setConfigValue(input.key, input.value, {
- isSecret: input.isSecret,
- category: input.category,
- description: input.description,
- });
- return { success: true };
- }),
-
- deleteConfig: adminProcedure
- .input(z.object({ key: z.string().max(100) }))
- .mutation(async ({ input }) => {
- await deleteConfigValue(input.key);
- return { success: true };
- }),
-
- testStripeConnection: adminProcedure
- .mutation(async () => {
- try {
- const configured = await isStripeConfigured();
- if (!configured) return { success: false, error: "Cle Stripe non configuree" };
- const stripe = await getStripe();
- await stripe.products.list({ limit: 1 });
- return { success: true };
- } catch (err) {
- const msg = err instanceof Error ? err.message : String(err);
- return { success: false, error: msg };
- }
- }),
-
- testSmsConnection: adminProcedure
- .mutation(async () => {
- try {
- const configured = await isSmsConfigured();
- if (!configured) return { success: false, error: "Twilio non configure" };
- return { success: true };
- } catch (err) {
- const msg = err instanceof Error ? err.message : String(err);
- return { success: false, error: msg };
- }
- }),
-
-});
-
-// ─── App router ──────────────────────────────────────────────────────────────
-export const appRouter = router({
- auth: authRouter,
- clinic: clinicRouter,
- queue: queueRouter,
- analytics: analyticsRouter,
- subscription: subscriptionRouter,
- whatsapp: whatsappRouter,
- notification: notificationRouter,
- clinicSettings: clinicSettingsRouter,
- history: historyRouter,
- admin: adminRouter,
-});
-
-export type AppRouter = typeof appRouter;
diff --git a/server/schema.ts b/server/schema.ts
deleted file mode 100644
index ecbfe72..0000000
--- a/server/schema.ts
+++ /dev/null
@@ -1,307 +0,0 @@
-import {
- int,
- mysqlEnum,
- mysqlTable,
- text,
- timestamp,
- tinyint,
- varchar,
- boolean,
- json,
- index,
- uniqueIndex,
-} from "drizzle-orm/mysql-core";
-
-// ─── Users (médecins) ────────────────────────────────────────────────────────
-export const users = mysqlTable(
- "users",
- {
- id: int("id").autoincrement().primaryKey(),
- email: varchar("email", { length: 320 }).notNull(),
- passwordHash: varchar("passwordHash", { length: 255 }).notNull(),
- name: text("name"),
- openId: varchar("openId", { length: 64 }),
- loginMethod: varchar("loginMethod", { length: 64 }).default("password").notNull(),
- role: mysqlEnum("role", ["user", "admin"]).default("user").notNull(),
- disabled: boolean("disabled").default(false).notNull(),
- resetToken: varchar("resetToken", { length: 255 }),
- resetTokenExpiry: timestamp("resetTokenExpiry"),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
- lastSignedIn: timestamp("lastSignedIn").defaultNow().notNull(),
- },
- (table) => ({
- emailIdx: uniqueIndex("users_email_idx").on(table.email),
- openIdIdx: index("users_openId_idx").on(table.openId),
- })
-);
-
-export type User = typeof users.$inferSelect;
-export type InsertUser = typeof users.$inferInsert;
-
-// ─── Subscriptions ───────────────────────────────────────────────────────────
-export const subscriptions = mysqlTable(
- "subscriptions",
- {
- id: int("id").autoincrement().primaryKey(),
- userId: int("userId").notNull(),
- stripeCustomerId: varchar("stripeCustomerId", { length: 128 }),
- stripeSubscriptionId: varchar("stripeSubscriptionId", { length: 128 }),
- stripePriceId: varchar("stripePriceId", { length: 128 }),
- plan: mysqlEnum("plan", ["trial", "basic", "pro"]).default("trial").notNull(),
- status: mysqlEnum("status", ["trialing", "active", "past_due", "canceled", "expired"])
- .default("trialing")
- .notNull(),
- trialStartedAt: timestamp("trialStartedAt").defaultNow().notNull(),
- trialEndsAt: timestamp("trialEndsAt").notNull(),
- currentPeriodStart: timestamp("currentPeriodStart"),
- currentPeriodEnd: timestamp("currentPeriodEnd"),
- canceledAt: timestamp("canceledAt"),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
- },
- (table) => ({
- userIdx: index("subscriptions_userId_idx").on(table.userId),
- })
-);
-
-export type Subscription = typeof subscriptions.$inferSelect;
-export type InsertSubscription = typeof subscriptions.$inferInsert;
-
-// ─── Clinics (cabinets médicaux) ─────────────────────────────────────────────
-export const clinics = mysqlTable(
- "clinics",
- {
- id: int("id").autoincrement().primaryKey(),
- userId: int("userId").notNull(),
- name: varchar("name", { length: 255 }).notNull(),
- address: text("address"),
- phone: varchar("phone", { length: 32 }),
- color: varchar("color", { length: 16 }).default("#10b981"),
- // Numéro WhatsApp Business du cabinet
- whatsappPhone: varchar("whatsappPhone", { length: 32 }),
- isActive: boolean("isActive").default(true).notNull(),
- // QR code token rotatif anti-triche
- qrToken: varchar("qrToken", { length: 64 }).notNull(),
- qrTokenExpiresAt: timestamp("qrTokenExpiresAt"),
- qrRotationMinutes: int("qrRotationMinutes").default(1440),
- // Paramètres file d'attente
- avgConsultationMinutes: int("avgConsultationMinutes").default(15),
- maxQueueSize: int("maxQueueSize").default(50),
- isQueueOpen: boolean("isQueueOpen").default(false).notNull(),
- currentTicketNumber: int("currentTicketNumber").default(0).notNull(),
- // Timer absent automatique : marque absent après N minutes sans réponse (0 = désactivé)
- autoAbsentMinutes: int("autoAbsentMinutes").default(0).notNull(),
- // Paramètres enrichis cabinet
- welcomeMessage: text("welcomeMessage"),
- // Horaires d'ouverture JSON : { monday: { open, close, closed }, ... }
- openingHours: json("openingHours"),
- // Langue de l'interface patient : "fr" | "en" | "ar" | "pt" | "es"
- patientLanguage: varchar("patientLanguage", { length: 8 }).default("fr"),
- // Templates WhatsApp personnalisables (null = template par défaut)
- whatsappTemplateJoined: text("whatsappTemplateJoined"),
- whatsappTemplateSoon: text("whatsappTemplateSoon"),
- whatsappTemplateCalled: text("whatsappTemplateCalled"),
- whatsappTemplateWithdrawn: text("whatsappTemplateWithdrawn"),
- // Activation des notifications SMS Twilio (opt-in par cabinet)
- // Migration: ALTER TABLE clinics ADD COLUMN smsEnabled TINYINT(1) NOT NULL DEFAULT 0
- smsEnabled: boolean("smsEnabled").default(false).notNull(),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
- },
- (table) => ({
- userIdx: index("clinics_userId_idx").on(table.userId),
- qrTokenIdx: uniqueIndex("clinics_qrToken_idx").on(table.qrToken),
- })
-);
-
-export type Clinic = typeof clinics.$inferSelect;
-export type InsertClinic = typeof clinics.$inferInsert;
-
-// ─── Queue Entries (patients en file) ────────────────────────────────────────
-export const queueEntries = mysqlTable(
- "queue_entries",
- {
- id: int("id").autoincrement().primaryKey(),
- clinicId: int("clinicId").notNull(),
- ticketNumber: int("ticketNumber").notNull(),
- // Identifiant de session anonyme du patient
- patientToken: varchar("patientToken", { length: 64 }).notNull(),
- patientName: varchar("patientName", { length: 128 }),
- patientPhone: varchar("patientPhone", { length: 32 }),
- status: mysqlEnum("status", [
- "waiting",
- "called",
- "in_consultation",
- "done",
- "absent",
- "canceled",
- ])
- .default("waiting")
- .notNull(),
- position: int("position").notNull(),
- joinedAt: timestamp("joinedAt").defaultNow().notNull(),
- calledAt: timestamp("calledAt"),
- consultationStartAt: timestamp("consultationStartAt"),
- consultationEndAt: timestamp("consultationEndAt"),
- estimatedWaitMinutes: int("estimatedWaitMinutes"),
- notificationSent: boolean("notificationSent").default(false).notNull(),
- // Motif de visite patient
- visitReason: mysqlEnum("visitReason", [
- "consultation",
- "urgence",
- "certificat_scolaire",
- "certificat_sportif",
- "arret_travail",
- "administratif",
- "autre",
- ]).default("consultation"),
- visitNote: text("visitNote"),
- // Praticien assigné (multi-praticiens par cabinet)
- practitionerId: int("practitionerId"),
- // Timing consultation supplémentaire (pour stats)
- consultationStartedAt: timestamp("consultationStartedAt"),
- // Notifications WhatsApp
- whatsappPhone: varchar("whatsappPhone", { length: 32 }),
- whatsappSentJoined: boolean("whatsappSentJoined").default(false).notNull(),
- whatsappSentSoon: boolean("whatsappSentSoon").default(false).notNull(),
- whatsappSentCalled: boolean("whatsappSentCalled").default(false).notNull(),
- // Pour l'impression de ticket
- isPrinted: boolean("isPrinted").default(false).notNull(),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
- },
- (table) => ({
- clinicIdx: index("queue_clinicId_idx").on(table.clinicId),
- statusIdx: index("queue_status_idx").on(table.status),
- tokenIdx: index("queue_patientToken_idx").on(table.patientToken),
- })
-);
-
-export type QueueEntry = typeof queueEntries.$inferSelect;
-export type InsertQueueEntry = typeof queueEntries.$inferInsert;
-
-// ─── Analytics Events ─────────────────────────────────────────────────────────
-export const analyticsEvents = mysqlTable(
- "analytics_events",
- {
- id: int("id").autoincrement().primaryKey(),
- clinicId: int("clinicId").notNull(),
- eventType: mysqlEnum("eventType", [
- "patient_joined",
- "patient_called",
- "patient_done",
- "patient_absent",
- "queue_opened",
- "queue_closed",
- ]).notNull(),
- ticketNumber: int("ticketNumber"),
- waitMinutes: int("waitMinutes"),
- consultationMinutes: int("consultationMinutes"),
- queueSizeAtEvent: int("queueSizeAtEvent"),
- hourOfDay: int("hourOfDay"),
- dayOfWeek: int("dayOfWeek"),
- metadata: json("metadata"),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- },
- (table) => ({
- clinicIdx: index("analytics_clinicId_idx").on(table.clinicId),
- createdIdx: index("analytics_createdAt_idx").on(table.createdAt),
- })
-);
-
-export type AnalyticsEvent = typeof analyticsEvents.$inferSelect;
-export type InsertAnalyticsEvent = typeof analyticsEvents.$inferInsert;
-
-// ─── WhatsApp Country Codes ──────────────────────────────────────────────────
-// Indicatifs pays disponibles pour les notifications WhatsApp patients
-export const whatsappCountryCodes = mysqlTable(
- "whatsapp_country_codes",
- {
- id: int("id").autoincrement().primaryKey(),
- code: varchar("code", { length: 4 }).notNull(),
- dialCode: varchar("dialCode", { length: 8 }).notNull(),
- nameFr: varchar("nameFr", { length: 128 }).notNull(),
- flag: varchar("flag", { length: 8 }).notNull(),
- enabled: boolean("enabled").default(false).notNull(),
- sortOrder: int("sortOrder").default(100).notNull(),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
- },
- (table) => ({
- codeIdx: uniqueIndex("whatsapp_country_codes_code_idx").on(table.code),
- })
-);
-
-export type WhatsappCountryCode = typeof whatsappCountryCodes.$inferSelect;
-export type InsertWhatsappCountryCode = typeof whatsappCountryCodes.$inferInsert;
-
-// ─── WhatsApp Logs ────────────────────────────────────────────────────────────
-// Trace chaque message WhatsApp envoyé par cabinet
-export const whatsappLogs = mysqlTable(
- "whatsapp_logs",
- {
- id: int("id").autoincrement().primaryKey(),
- clinicId: int("clinicId").notNull(),
- phoneMasked: varchar("phoneMasked", { length: 32 }).notNull(),
- messageType: mysqlEnum("messageType", ["joined", "soon", "called", "withdrawn", "test"]).notNull(),
- status: mysqlEnum("status", ["sent", "failed"]).notNull(),
- errorMessage: text("errorMessage"),
- messagePreview: varchar("messagePreview", { length: 120 }),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- },
- (table) => ({
- clinicIdx: index("whatsapp_logs_clinicId_idx").on(table.clinicId),
- createdIdx: index("whatsapp_logs_createdAt_idx").on(table.createdAt),
- })
-);
-
-export type WhatsappLog = typeof whatsappLogs.$inferSelect;
-export type InsertWhatsappLog = typeof whatsappLogs.$inferInsert;
-
-// ─── Clinic Members (multi-praticiens par cabinet) ───────────────────────────
-export const clinicMembers = mysqlTable(
- "clinic_members",
- {
- id: int("id").autoincrement().primaryKey(),
- clinicId: int("clinicId").notNull(),
- userId: int("userId").notNull(),
- role: mysqlEnum("role", ["owner", "practitioner"]).default("practitioner").notNull(),
- color: varchar("color", { length: 7 }).default("#10b981").notNull(),
- displayName: varchar("displayName", { length: 128 }),
- createdAt: timestamp("createdAt").defaultNow().notNull(),
- },
- (table) => ({
- clinicIdx: index("clinic_members_clinicId_idx").on(table.clinicId),
- userIdx: index("clinic_members_userId_idx").on(table.userId),
- uniqueMember: uniqueIndex("clinic_members_unique_idx").on(table.clinicId, table.userId),
- })
-);
-
-export type ClinicMember = typeof clinicMembers.$inferSelect;
-export type InsertClinicMember = typeof clinicMembers.$inferInsert;
-
-// ─── App Config (intégrations & secrets dynamiques) ──────────────────────────
-// Permet de configurer Stripe / Twilio / autres services depuis l'UI admin
-// sans redéploiement. Les valeurs marquées comme secrètes sont masquées
-// côté API et ne sont jamais renvoyées en clair (sauf via les services
-// internes qui les consomment).
-export const appConfig = mysqlTable(
- "app_config",
- {
- id: int("id").primaryKey().autoincrement(),
- key: varchar("key", { length: 100 }).notNull(),
- value: text("value").notNull(),
- isSecret: tinyint("is_secret").default(0).notNull(),
- category: varchar("category", { length: 50 }).notNull(),
- description: varchar("description", { length: 255 }),
- updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
- },
- (table) => ({
- keyIdx: uniqueIndex("app_config_key_idx").on(table.key),
- categoryIdx: index("app_config_category_idx").on(table.category),
- })
-);
-
-export type AppConfig = typeof appConfig.$inferSelect;
-export type InsertAppConfig = typeof appConfig.$inferInsert;
diff --git a/server/services/autoAbsent.ts b/server/services/autoAbsent.ts
deleted file mode 100644
index 758a284..0000000
--- a/server/services/autoAbsent.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * Auto-Absent Timer Service
- * Vérifie toutes les 30 secondes les patients en statut "called" depuis plus de N minutes.
- * Si autoAbsentMinutes > 0 pour le cabinet, le patient est marqué absent et le suivant est appelé.
- */
-import { getDb } from "../db.js";
-import { clinics, queueEntries } from "../schema.js";
-import { eq, and, inArray } from "drizzle-orm";
-import { childLogger } from "../_core/logger.js";
-
-const log = childLogger("auto-absent");
-// Socket.io helpers (utilise le global injecté par le serveur principal)
-function emitToClinic(clinicId: number, event: string, data: unknown) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const io = (global as any).__socketIo;
- if (io) io.to(`clinic:${clinicId}`).emit(event, data);
-}
-
-function emitToPatient(patientToken: string, event: string, data: unknown) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const io = (global as any).__socketIo;
- if (io) io.to(`patient:${patientToken}`).emit(event, data);
-}
-
-let intervalId: ReturnType | null = null;
-
-/** Démarre le job de vérification des absents automatiques */
-export function startAutoAbsentJob(): void {
- if (intervalId) return; // already running
- intervalId = setInterval(checkAutoAbsent, 30_000);
- log.info("job started (interval 30s)");
-}
-
-/** Arrête le job */
-export function stopAutoAbsentJob(): void {
- if (intervalId) {
- clearInterval(intervalId);
- intervalId = null;
- log.info("job stopped");
- }
-}
-
-async function checkAutoAbsent(): Promise {
- const db = await getDb();
- if (!db) return;
-
- try {
- // Récupérer tous les cabinets avec autoAbsentMinutes > 0
- const activeClinics = await db
- .select({
- id: clinics.id,
- autoAbsentMinutes: clinics.autoAbsentMinutes,
- avgConsultationMinutes: clinics.avgConsultationMinutes,
- name: clinics.name,
- })
- .from(clinics)
- .where(and(
- eq(clinics.isActive, true),
- eq(clinics.isQueueOpen, true),
- ));
-
- const clinicsWithTimer = activeClinics.filter(
- (c) => (c.autoAbsentMinutes ?? 0) > 0
- );
-
- if (clinicsWithTimer.length === 0) return;
-
- const now = new Date();
-
- for (const clinic of clinicsWithTimer) {
- const thresholdMs = (clinic.autoAbsentMinutes ?? 3) * 60 * 1000;
-
- // Récupérer les patients en statut "called" pour ce cabinet
- const calledEntries = await db
- .select()
- .from(queueEntries)
- .where(and(
- eq(queueEntries.clinicId, clinic.id),
- eq(queueEntries.status, "called"),
- ));
-
- for (const entry of calledEntries) {
- if (!entry.calledAt) continue;
- const elapsed = now.getTime() - entry.calledAt.getTime();
-
- if (elapsed >= thresholdMs) {
- // Marquer absent
- await db
- .update(queueEntries)
- .set({ status: "absent" })
- .where(eq(queueEntries.id, entry.id));
-
- log.info(
- {
- clinicId: clinic.id,
- ticketNumber: entry.ticketNumber,
- elapsedMinutes: Math.round(elapsed / 60000),
- },
- "patient marked absent"
- );
-
- // Notifier le patient (s'il est encore connecté)
- if (entry.patientToken) {
- emitToPatient(entry.patientToken, "patient:auto_absent", {
- ticketNumber: entry.ticketNumber,
- message: `Votre ticket n°${entry.ticketNumber} a été annulé car vous n'étiez pas présent.`,
- });
- }
-
- // Reordonner la file et notifier le cabinet
- await reorderAndNotify(clinic.id, db);
- }
- }
- }
- } catch (err) {
- log.error({ err }, "check failed");
- }
-}
-
-async function reorderAndNotify(clinicId: number, db: Awaited>): Promise {
- if (!db) return;
-
- // Récupérer les patients en attente pour ce cabinet
- const waitingEntries = await db
- .select()
- .from(queueEntries)
- .where(and(
- eq(queueEntries.clinicId, clinicId),
- eq(queueEntries.status, "waiting"),
- ));
-
- // Renuméroter
- let pos = 1;
- for (const e of waitingEntries.sort((a, b) => (a.position ?? 0) - (b.position ?? 0))) {
- await db
- .update(queueEntries)
- .set({ position: pos })
- .where(eq(queueEntries.id, e.id));
- pos++;
- }
-
- // Calculer l'état de la file pour la notification WebSocket
- const allActive = await db
- .select()
- .from(queueEntries)
- .where(and(
- eq(queueEntries.clinicId, clinicId),
- inArray(queueEntries.status, ["waiting", "called", "in_consultation"]),
- ));
-
- const state = {
- totalWaiting: allActive.filter((e) => e.status === "waiting").length,
- currentTicket: allActive.find((e) => e.status === "called")?.ticketNumber ?? null,
- clinicId,
- };
-
- emitToClinic(clinicId, "queue:update", state);
- emitToClinic(clinicId, "display:update", state);
-}
diff --git a/server/services/email.ts b/server/services/email.ts
deleted file mode 100644
index e0a1da4..0000000
--- a/server/services/email.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import nodemailer, { type Transporter } from "nodemailer";
-import { childLogger } from "../_core/logger.js";
-
-const log = childLogger("email");
-
-let cachedTransporter: Transporter | null = null;
-
-function getTransporter(): Transporter | null {
- if (cachedTransporter) return cachedTransporter;
- const host = process.env.SMTP_HOST;
- const port = process.env.SMTP_PORT ? Number(process.env.SMTP_PORT) : undefined;
- const user = process.env.SMTP_USER;
- const pass = process.env.SMTP_PASS;
- if (!host || !port) {
- log.warn("SMTP_HOST/SMTP_PORT not configured — emails will be logged only");
- return null;
- }
- cachedTransporter = nodemailer.createTransport({
- host,
- port,
- secure: port === 465,
- auth: user && pass ? { user, pass } : undefined,
- });
- return cachedTransporter;
-}
-
-export async function sendMail(opts: { to: string; subject: string; html: string; text?: string }): Promise {
- const from = process.env.SMTP_FROM ?? process.env.SMTP_USER ?? "no-reply@queuemed.app";
- const transporter = getTransporter();
- if (!transporter) {
- log.info({ to: opts.to, subject: opts.subject }, "(dev) would send email");
- return;
- }
- await transporter.sendMail({
- from,
- to: opts.to,
- subject: opts.subject,
- html: opts.html,
- text: opts.text,
- });
-}
-
-export function buildResetEmail(resetUrl: string): { subject: string; html: string; text: string } {
- const subject = "QueueMed — Réinitialisation de votre mot de passe";
- const text = `Bonjour,\n\nVous avez demandé à réinitialiser votre mot de passe QueueMed.\n\nCliquez sur ce lien (valable 1 heure) :\n${resetUrl}\n\nSi vous n'êtes pas à l'origine de cette demande, ignorez ce message.\n\n— L'équipe QueueMed`;
- const html = `
-
-
-
Réinitialisation de votre mot de passe
-
Bonjour,
-
Vous avez demandé à réinitialiser votre mot de passe QueueMed. Cliquez sur le bouton ci-dessous (valable 1 heure) :
-
- Réinitialiser mon mot de passe
-
-
Si vous n'êtes pas à l'origine de cette demande, ignorez ce message.
-
-
— L'équipe QueueMed
-
-`;
- return { subject, html, text };
-}
diff --git a/server/services/pdfReport.ts b/server/services/pdfReport.ts
deleted file mode 100644
index dcf4d40..0000000
--- a/server/services/pdfReport.ts
+++ /dev/null
@@ -1,298 +0,0 @@
-/**
- * PDF report generator (queue analytics) using pdfkit.
- *
- * generateQueueReport returns a Buffer containing the binary PDF, ready to
- * be base64-encoded and shipped to the client. All sections handle empty
- * data sets gracefully so a freshly-onboarded clinic still gets a valid PDF.
- */
-
-import PDFDocument from "pdfkit";
-import {
- getClinicById,
- getAdvancedAnalytics,
- getConsultationStats,
-} from "../db.js";
-import { childLogger } from "../_core/logger.js";
-
-const log = childLogger("pdf-report");
-
-// QueueMed medical theme
-const COLOR_PRIMARY = "#10b981"; // emerald-500
-const COLOR_ACCENT = "#06b6d4"; // cyan-500
-const COLOR_TEAL = "#0d9488"; // teal-600
-const COLOR_TEXT = "#0f172a"; // slate-900
-const COLOR_MUTED = "#64748b"; // slate-500
-const COLOR_BORDER = "#e2e8f0"; // slate-200
-const COLOR_BG_SOFT = "#f0fdf4"; // green-50
-
-const REASON_LABELS: Record = {
- consultation: "Consultation",
- urgence: "Urgence",
- certificat_scolaire: "Certificat scolaire",
- certificat_sportif: "Certificat sportif",
- arret_travail: "Arrêt de travail",
- administratif: "Administratif",
- autre: "Autre",
-};
-
-function formatDate(d: Date): string {
- return d.toLocaleDateString("fr-FR", {
- day: "2-digit",
- month: "long",
- year: "numeric",
- });
-}
-
-export async function generateQueueReport(
- clinicId: number,
- dateRange: { days: number }
-): Promise {
- const days = Math.max(1, Math.min(dateRange.days ?? 30, 365));
- const clinic = await getClinicById(clinicId);
- if (!clinic) throw new Error(`Clinic ${clinicId} introuvable`);
-
- // Fetch the same data the dashboard renders so the PDF matches the UI.
- const [advanced, consult] = await Promise.all([
- getAdvancedAnalytics(clinic.userId, { days, clinicId }),
- getConsultationStats(clinicId, days),
- ]);
-
- const now = new Date();
- const since = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
-
- const doc = new PDFDocument({
- size: "A4",
- margin: 48,
- info: {
- Title: `QueueMed — Rapport ${clinic.name}`,
- Author: "QueueMed",
- Subject: "Rapport file d'attente",
- Creator: "QueueMed",
- },
- });
-
- const chunks: Buffer[] = [];
- doc.on("data", (c: Buffer) => chunks.push(c));
- const finished = new Promise((resolve, reject) => {
- doc.on("end", () => resolve(Buffer.concat(chunks)));
- doc.on("error", reject);
- });
-
- // ─── Header ────────────────────────────────────────────────────────────────
- doc
- .rect(0, 0, doc.page.width, 90)
- .fill(COLOR_PRIMARY);
- doc
- .fillColor("#ffffff")
- .fontSize(22)
- .font("Helvetica-Bold")
- .text("QueueMed — Rapport file d'attente", 48, 28);
- doc
- .fontSize(11)
- .font("Helvetica")
- .fillColor("#ecfeff")
- .text(`Cabinet : ${clinic.name}`, 48, 58);
- doc.text(
- `Période : ${formatDate(since)} → ${formatDate(now)} (${days} j)`,
- 48,
- 72
- );
-
- doc.fillColor(COLOR_TEXT);
- doc.y = 120;
- doc.x = 48;
-
- // ─── Summary table ─────────────────────────────────────────────────────────
- doc
- .fontSize(14)
- .font("Helvetica-Bold")
- .fillColor(COLOR_TEAL)
- .text("Résumé", { underline: false });
- doc.moveDown(0.4);
-
- const totalJoined = advanced.totalJoined;
- const totalServed = advanced.totalServed;
- const totalAbsent = advanced.totalAbsent;
- const noShowPct = Math.round((advanced.noShowRate ?? 0) * 100);
- const totalConsults = consult.totalConsultations;
- const avgConsultMin = consult.avgDurationMinutes;
- const presenceRate = consult.presenceRate;
-
- // Compute average wait from byHour aggregates is not direct — use avgWaitByDay
- const allDays = advanced.avgWaitByDay;
- const totalWait = allDays.reduce(
- (acc, d) => acc + d.avgWaitMinutes * d.count,
- 0
- );
- const totalWaitCount = allDays.reduce((acc, d) => acc + d.count, 0);
- const avgWaitMin = totalWaitCount > 0 ? Math.round(totalWait / totalWaitCount) : 0;
-
- const summaryRows: Array<[string, string]> = [
- ["Patients inscrits", String(totalJoined)],
- ["Patients servis", String(totalServed)],
- ["Patients absents", String(totalAbsent)],
- ["Taux d'absence", `${noShowPct}%`],
- ["Taux de présence", `${presenceRate}%`],
- ["Attente moyenne", `${avgWaitMin} min`],
- ["Consultations terminées", String(totalConsults)],
- ["Durée moy. consultation", `${avgConsultMin} min`],
- ];
-
- drawKeyValueTable(doc, summaryRows);
-
- doc.moveDown(1);
-
- // ─── By-hour breakdown ─────────────────────────────────────────────────────
- doc
- .fontSize(14)
- .font("Helvetica-Bold")
- .fillColor(COLOR_TEAL)
- .text("Affluence par heure");
- doc.moveDown(0.4);
-
- const hourRows = advanced.byHour
- .map((count, hour) => ({ hour, count }))
- .filter((r) => r.count > 0);
-
- if (hourRows.length === 0) {
- doc
- .fontSize(10)
- .font("Helvetica-Oblique")
- .fillColor(COLOR_MUTED)
- .text("Aucune donnée d'affluence sur la période.");
- } else {
- const maxCount = Math.max(...hourRows.map((r) => r.count));
- drawTableHeader(doc, ["Heure", "Patients", "Répartition"], [80, 80, 320]);
- for (const r of hourRows) {
- ensureSpace(doc, 22);
- const y = doc.y;
- doc
- .font("Helvetica")
- .fontSize(10)
- .fillColor(COLOR_TEXT)
- .text(`${r.hour.toString().padStart(2, "0")}h`, 48, y, { width: 80 });
- doc.text(String(r.count), 128, y, { width: 80 });
- // Bar
- const barX = 208;
- const barMaxW = 300;
- const barW = Math.max(4, Math.round((r.count / maxCount) * barMaxW));
- doc.rect(barX, y + 3, barW, 8).fill(COLOR_PRIMARY);
- doc.fillColor(COLOR_TEXT);
- doc.y = y + 18;
- }
- }
-
- doc.moveDown(1);
-
- // ─── Top visit reasons ─────────────────────────────────────────────────────
- doc
- .fontSize(14)
- .font("Helvetica-Bold")
- .fillColor(COLOR_TEAL)
- .text("Motifs de consultation");
- doc.moveDown(0.4);
-
- if (consult.topReasons.length === 0) {
- doc
- .fontSize(10)
- .font("Helvetica-Oblique")
- .fillColor(COLOR_MUTED)
- .text("Aucun motif de consultation enregistré.");
- } else {
- drawTableHeader(doc, ["Motif", "Nombre", "Part"], [240, 80, 120]);
- const topTotal = consult.topReasons.reduce((s, r) => s + r.count, 0);
- for (const r of consult.topReasons) {
- ensureSpace(doc, 18);
- const y = doc.y;
- const label = REASON_LABELS[r.reason] ?? r.reason;
- const pct = topTotal > 0 ? Math.round((r.count / topTotal) * 100) : 0;
- doc
- .font("Helvetica")
- .fontSize(10)
- .fillColor(COLOR_TEXT)
- .text(label, 48, y, { width: 240 });
- doc.text(String(r.count), 288, y, { width: 80 });
- doc.text(`${pct}%`, 368, y, { width: 120 });
- doc.y = y + 16;
- }
- }
-
- // ─── Footer ────────────────────────────────────────────────────────────────
- const footerY = doc.page.height - 36;
- doc
- .fontSize(9)
- .font("Helvetica")
- .fillColor(COLOR_MUTED)
- .text(
- `Généré par QueueMed le ${now.toLocaleString("fr-FR")}`,
- 48,
- footerY,
- { align: "center", width: doc.page.width - 96 }
- );
-
- doc.end();
-
- try {
- return await finished;
- } catch (err) {
- log.error({ err, clinicId }, "PDF generation failed");
- throw err;
- }
-}
-
-// ─── Helpers ─────────────────────────────────────────────────────────────────
-function ensureSpace(doc: PDFKit.PDFDocument, needed: number): void {
- if (doc.y + needed > doc.page.height - 60) {
- doc.addPage();
- }
-}
-
-function drawKeyValueTable(
- doc: PDFKit.PDFDocument,
- rows: Array<[string, string]>
-): void {
- const colKeyW = 260;
- const colValW = 240;
- const x = 48;
- for (const [k, v] of rows) {
- ensureSpace(doc, 22);
- const y = doc.y;
- doc
- .rect(x, y, colKeyW + colValW, 20)
- .fill(COLOR_BG_SOFT)
- .stroke(COLOR_BORDER);
- doc
- .font("Helvetica")
- .fontSize(10)
- .fillColor(COLOR_TEXT)
- .text(k, x + 8, y + 6, { width: colKeyW - 16 });
- doc
- .font("Helvetica-Bold")
- .fillColor(COLOR_TEAL)
- .text(v, x + colKeyW, y + 6, { width: colValW - 8, align: "right" });
- doc.y = y + 22;
- }
- doc.fillColor(COLOR_TEXT);
-}
-
-function drawTableHeader(
- doc: PDFKit.PDFDocument,
- headers: string[],
- widths: number[]
-): void {
- ensureSpace(doc, 22);
- const x = 48;
- const y = doc.y;
- doc.rect(x, y, widths.reduce((a, b) => a + b, 0), 20).fill(COLOR_PRIMARY);
- let cx = x;
- for (let i = 0; i < headers.length; i++) {
- doc
- .font("Helvetica-Bold")
- .fontSize(10)
- .fillColor("#ffffff")
- .text(headers[i], cx + 8, y + 6, { width: widths[i] - 16 });
- cx += widths[i];
- }
- doc.fillColor(COLOR_TEXT);
- doc.y = y + 22;
-}
diff --git a/server/services/planLimits.ts b/server/services/planLimits.ts
deleted file mode 100644
index e5a2339..0000000
--- a/server/services/planLimits.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-import { and, eq, gte } from "drizzle-orm";
-import { getDb, getSubscription } from "../db.js";
-import { clinics, queueEntries } from "../schema.js";
-import { sql } from "drizzle-orm";
-
-export type PlanFeature =
- | "maxClinics"
- | "maxQueueEntriesPerDay"
- | "multiPractitioner"
- | "analyticsExport";
-
-type PlanLimits = {
- maxClinics: number;
- maxQueueEntriesPerDay: number;
- multiPractitioner: boolean;
- analyticsExport: boolean;
-};
-
-// trial == basic level access during trial period; pro lifts everything.
-export const PLAN_LIMITS: Record<"trial" | "basic" | "pro", PlanLimits> = {
- trial: {
- maxClinics: 1,
- maxQueueEntriesPerDay: 50,
- multiPractitioner: false,
- analyticsExport: false,
- },
- basic: {
- maxClinics: 1,
- maxQueueEntriesPerDay: 200,
- multiPractitioner: false,
- analyticsExport: true,
- },
- pro: {
- maxClinics: Infinity,
- maxQueueEntriesPerDay: Infinity,
- multiPractitioner: true,
- analyticsExport: true,
- },
-};
-
-export type PlanLimitCheck =
- | { ok: true }
- | { ok: false; reason: string; feature: PlanFeature };
-
-async function getUserPlan(userId: number): Promise<"trial" | "basic" | "pro"> {
- const sub = await getSubscription(userId);
- return sub?.plan ?? "trial";
-}
-
-function limits(plan: "trial" | "basic" | "pro"): PlanLimits {
- return PLAN_LIMITS[plan];
-}
-
-async function countClinicsForUser(userId: number): Promise {
- const db = await getDb();
- const rows = await db
- .select({ count: sql`COUNT(*)` })
- .from(clinics)
- .where(eq(clinics.userId, userId));
- return Number(rows[0]?.count ?? 0);
-}
-
-async function countQueueEntriesTodayForClinic(clinicId: number): Promise {
- const db = await getDb();
- const startOfDay = new Date();
- startOfDay.setHours(0, 0, 0, 0);
- const rows = await db
- .select({ count: sql`COUNT(*)` })
- .from(queueEntries)
- .where(
- and(eq(queueEntries.clinicId, clinicId), gte(queueEntries.joinedAt, startOfDay))
- );
- return Number(rows[0]?.count ?? 0);
-}
-
-const FEATURE_MESSAGES: Record = {
- maxClinics: "Limite de cabinets atteinte : passez au plan Pro pour en créer plus.",
- maxQueueEntriesPerDay:
- "Limite quotidienne de patients atteinte : passez au plan Pro pour des inscriptions illimitées.",
- multiPractitioner:
- "La gestion multi-praticiens est réservée au plan Pro. Mettez à niveau pour ajouter des praticiens.",
- analyticsExport:
- "L'export des statistiques est réservé aux plans payants. Mettez à niveau pour exporter vos données.",
-};
-
-export async function checkPlanLimit(
- userId: number,
- feature: PlanFeature,
- context: { clinicId?: number } = {}
-): Promise {
- const plan = await getUserPlan(userId);
- const max = limits(plan);
-
- switch (feature) {
- case "maxClinics": {
- if (max.maxClinics === Infinity) return { ok: true };
- const current = await countClinicsForUser(userId);
- if (current >= max.maxClinics) {
- return { ok: false, feature, reason: FEATURE_MESSAGES.maxClinics };
- }
- return { ok: true };
- }
- case "maxQueueEntriesPerDay": {
- if (max.maxQueueEntriesPerDay === Infinity) return { ok: true };
- if (!context.clinicId) return { ok: true };
- const today = await countQueueEntriesTodayForClinic(context.clinicId);
- if (today >= max.maxQueueEntriesPerDay) {
- return {
- ok: false,
- feature,
- reason: FEATURE_MESSAGES.maxQueueEntriesPerDay,
- };
- }
- return { ok: true };
- }
- case "multiPractitioner": {
- if (max.multiPractitioner) return { ok: true };
- return { ok: false, feature, reason: FEATURE_MESSAGES.multiPractitioner };
- }
- case "analyticsExport": {
- if (max.analyticsExport) return { ok: true };
- return { ok: false, feature, reason: FEATURE_MESSAGES.analyticsExport };
- }
- }
-}
-
-export async function getPlanLimitsForUser(userId: number): Promise<{
- plan: "trial" | "basic" | "pro";
- limits: PlanLimits;
-}> {
- const plan = await getUserPlan(userId);
- return { plan, limits: limits(plan) };
-}
diff --git a/server/services/sms.ts b/server/services/sms.ts
deleted file mode 100644
index 7c45458..0000000
--- a/server/services/sms.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * SMS notification service using Twilio.
- *
- * Reads TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER from the
- * app_config table first, then falls back to env vars. If any of those are
- * missing, sendSms is a no-op that returns { success: false } and logs a
- * warning. This keeps the app running in environments where Twilio has not
- * been provisioned yet.
- */
-
-import twilio, { type Twilio } from "twilio";
-import { childLogger } from "../_core/logger.js";
-import { getConfigValue } from "../db.js";
-
-const log = childLogger("sms");
-
-let cachedClient: Twilio | null = null;
-let cachedClientSid: string | null = null;
-
-async function resolveTwilioConfig(): Promise<{
- sid: string | null;
- token: string | null;
- phone: string | null;
-}> {
- const [sid, token, phone] = await Promise.all([
- getConfigValue("TWILIO_ACCOUNT_SID"),
- getConfigValue("TWILIO_AUTH_TOKEN"),
- getConfigValue("TWILIO_PHONE_NUMBER"),
- ]);
- return {
- sid: sid ?? process.env.TWILIO_ACCOUNT_SID ?? null,
- token: token ?? process.env.TWILIO_AUTH_TOKEN ?? null,
- phone: phone ?? process.env.TWILIO_PHONE_NUMBER ?? null,
- };
-}
-
-export async function isSmsConfigured(): Promise {
- const cfg = await resolveTwilioConfig();
- return Boolean(cfg.sid && cfg.token && cfg.phone);
-}
-
-async function getClient(): Promise<{ client: Twilio; from: string } | null> {
- const cfg = await resolveTwilioConfig();
- if (!cfg.sid || !cfg.token || !cfg.phone) return null;
- if (cachedClient && cachedClientSid === cfg.sid) {
- return { client: cachedClient, from: cfg.phone };
- }
- try {
- cachedClient = twilio(cfg.sid, cfg.token);
- cachedClientSid = cfg.sid;
- return { client: cachedClient, from: cfg.phone };
- } catch (err) {
- log.error({ err }, "failed to initialise Twilio client");
- return null;
- }
-}
-
-function normalizePhone(input: string): string {
- const trimmed = input.trim();
- if (trimmed.startsWith("+")) return trimmed;
- const digits = trimmed.replace(/[^0-9]/g, "");
- return `+${digits}`;
-}
-
-export async function sendSms(
- to: string,
- body: string
-): Promise<{ success: boolean; messageId?: string; error?: string }> {
- const ctx = await getClient();
- if (!ctx) {
- log.warn({ to: to.slice(0, 4) + "***" }, "Twilio not configured — SMS skipped");
- return { success: false, error: "Twilio non configuré" };
- }
-
- const normalized = normalizePhone(to);
-
- try {
- const msg = await ctx.client.messages.create({
- to: normalized,
- from: ctx.from,
- body,
- });
- log.info({ messageId: msg.sid, to: normalized.slice(0, 4) + "***" }, "SMS sent");
- return { success: true, messageId: msg.sid };
- } catch (err) {
- const errorMessage = err instanceof Error ? err.message : String(err);
- log.error({ err, to: normalized.slice(0, 4) + "***" }, "SMS send failed");
- return { success: false, error: errorMessage };
- }
-}
diff --git a/server/services/stripe.ts b/server/services/stripe.ts
deleted file mode 100644
index a863580..0000000
--- a/server/services/stripe.ts
+++ /dev/null
@@ -1,288 +0,0 @@
-import Stripe from "stripe";
-import { eq, desc } from "drizzle-orm";
-import { getDb, getSubscription, getUserById, updateSubscription, getConfigValue } from "../db.js";
-import { subscriptions } from "../schema.js";
-
-let stripeInstance: Stripe | null = null;
-let stripeInstanceKey: string | null = null;
-
-async function resolveStripeKey(): Promise {
- const dbKey = await getConfigValue("STRIPE_SECRET_KEY");
- if (dbKey) return dbKey;
- return process.env.STRIPE_SECRET_KEY ?? null;
-}
-
-export async function getStripe(): Promise {
- const key = await resolveStripeKey();
- if (!key) {
- throw new Error("STRIPE_SECRET_KEY is not set");
- }
- if (stripeInstance && stripeInstanceKey === key) return stripeInstance;
- stripeInstance = new Stripe(key, {
- apiVersion: "2026-04-22.dahlia",
- typescript: true,
- });
- stripeInstanceKey = key;
- return stripeInstance;
-}
-
-export async function isStripeConfigured(): Promise {
- const key = await resolveStripeKey();
- return Boolean(key);
-}
-
-async function resolvePriceId(envName: string, configKey: string): Promise {
- const dbVal = await getConfigValue(configKey);
- if (dbVal) return dbVal;
- return process.env[envName] ?? null;
-}
-
-function publicBaseUrl(): string {
- const url = process.env.PUBLIC_BASE_URL ?? "";
- if (!url) {
- throw new Error("PUBLIC_BASE_URL is not set");
- }
- return url.replace(/\/$/, "");
-}
-
-async function ensureStripeCustomer(userId: number): Promise {
- const sub = await getSubscription(userId);
- if (sub?.stripeCustomerId) return sub.stripeCustomerId;
- const user = await getUserById(userId);
- if (!user) throw new Error("User not found");
- const stripe = await getStripe();
- const customer = await stripe.customers.create({
- email: user.email,
- name: user.name ?? undefined,
- metadata: { userId: String(userId) },
- });
- await updateSubscription(userId, { stripeCustomerId: customer.id });
- return customer.id;
-}
-
-export async function createCheckoutSession(
- userId: number,
- priceId: string
-): Promise<{ url: string; sessionId: string }> {
- const stripe = await getStripe();
- const customerId = await ensureStripeCustomer(userId);
- const base = publicBaseUrl();
- const session = await stripe.checkout.sessions.create({
- mode: "subscription",
- customer: customerId,
- line_items: [{ price: priceId, quantity: 1 }],
- success_url: `${base}/subscription/success?session_id={CHECKOUT_SESSION_ID}`,
- cancel_url: `${base}/subscription/cancel`,
- allow_promotion_codes: true,
- subscription_data: { metadata: { userId: String(userId) } },
- metadata: { userId: String(userId) },
- });
- if (!session.url) throw new Error("Stripe Checkout did not return a URL");
- return { url: session.url, sessionId: session.id };
-}
-
-export async function createPortalSession(userId: number): Promise<{ url: string }> {
- const stripe = await getStripe();
- const sub = await getSubscription(userId);
- if (!sub?.stripeCustomerId) {
- throw new Error("No Stripe customer for this user yet");
- }
- const base = publicBaseUrl();
- const portal = await stripe.billingPortal.sessions.create({
- customer: sub.stripeCustomerId,
- return_url: `${base}/dashboard/subscription`,
- });
- return { url: portal.url };
-}
-
-export async function getSubscriptionStatus(userId: number): Promise<{
- plan: "trial" | "basic" | "pro" | null;
- status: string | null;
- currentPeriodEnd: Date | null;
- trialEndsAt: Date | null;
- stripeCustomerId: string | null;
- stripeSubscriptionId: string | null;
-} | null> {
- const sub = await getSubscription(userId);
- if (!sub) return null;
- return {
- plan: sub.plan,
- status: sub.status,
- currentPeriodEnd: sub.currentPeriodEnd,
- trialEndsAt: sub.trialEndsAt,
- stripeCustomerId: sub.stripeCustomerId,
- stripeSubscriptionId: sub.stripeSubscriptionId,
- };
-}
-
-async function planFromPriceId(priceId: string | null | undefined): Promise<"basic" | "pro"> {
- const proPriceId = await resolvePriceId("STRIPE_PRO_PRICE_ID", "STRIPE_PRO_PRICE_ID");
- if (priceId && proPriceId && priceId === proPriceId) return "pro";
- return "basic";
-}
-
-async function findUserBySubscriptionId(
- stripeSubscriptionId: string
-): Promise {
- const db = await getDb();
- const rows = await db
- .select()
- .from(subscriptions)
- .where(eq(subscriptions.stripeSubscriptionId, stripeSubscriptionId))
- .orderBy(desc(subscriptions.createdAt))
- .limit(1);
- return rows[0]?.userId ?? null;
-}
-
-async function findUserByCustomerId(stripeCustomerId: string): Promise {
- const db = await getDb();
- const rows = await db
- .select()
- .from(subscriptions)
- .where(eq(subscriptions.stripeCustomerId, stripeCustomerId))
- .orderBy(desc(subscriptions.createdAt))
- .limit(1);
- return rows[0]?.userId ?? null;
-}
-
-function toDate(epochSeconds: number | null | undefined): Date | null {
- if (!epochSeconds) return null;
- return new Date(epochSeconds * 1000);
-}
-
-function mapStripeStatus(
- s: Stripe.Subscription.Status
-): "trialing" | "active" | "past_due" | "canceled" | "expired" {
- switch (s) {
- case "trialing":
- return "trialing";
- case "active":
- return "active";
- case "past_due":
- case "unpaid":
- return "past_due";
- case "canceled":
- return "canceled";
- case "incomplete":
- case "incomplete_expired":
- case "paused":
- return "expired";
- default:
- return "expired";
- }
-}
-
-async function syncSubscriptionFromStripe(
- userId: number,
- subscription: Stripe.Subscription
-): Promise {
- const item = subscription.items.data[0];
- const priceId = item?.price?.id ?? null;
- const plan = await planFromPriceId(priceId);
- const status = mapStripeStatus(subscription.status);
- await updateSubscription(userId, {
- stripeSubscriptionId: subscription.id,
- stripeCustomerId:
- typeof subscription.customer === "string"
- ? subscription.customer
- : subscription.customer.id,
- stripePriceId: priceId,
- plan,
- status,
- currentPeriodStart: toDate(item?.current_period_start ?? null),
- currentPeriodEnd: toDate(item?.current_period_end ?? null),
- canceledAt: toDate(subscription.canceled_at),
- });
-}
-
-export async function handleWebhook(event: Stripe.Event): Promise {
- const stripe = await getStripe();
- switch (event.type) {
- case "checkout.session.completed": {
- const session = event.data.object as Stripe.Checkout.Session;
- const userIdRaw = session.metadata?.userId;
- const userId = userIdRaw ? Number(userIdRaw) : null;
- if (!userId || Number.isNaN(userId)) return;
- if (typeof session.subscription === "string") {
- const sub = await stripe.subscriptions.retrieve(session.subscription);
- await syncSubscriptionFromStripe(userId, sub);
- }
- break;
- }
- case "customer.subscription.created":
- case "customer.subscription.updated": {
- const sub = event.data.object as Stripe.Subscription;
- const metaUserId = sub.metadata?.userId ? Number(sub.metadata.userId) : null;
- let userId = metaUserId && !Number.isNaN(metaUserId) ? metaUserId : null;
- if (!userId) {
- userId = await findUserBySubscriptionId(sub.id);
- }
- if (!userId) {
- const customerId =
- typeof sub.customer === "string" ? sub.customer : sub.customer.id;
- userId = await findUserByCustomerId(customerId);
- }
- if (!userId) return;
- await syncSubscriptionFromStripe(userId, sub);
- break;
- }
- case "customer.subscription.deleted": {
- const sub = event.data.object as Stripe.Subscription;
- let userId = await findUserBySubscriptionId(sub.id);
- if (!userId) {
- const customerId =
- typeof sub.customer === "string" ? sub.customer : sub.customer.id;
- userId = await findUserByCustomerId(customerId);
- }
- if (!userId) return;
- await updateSubscription(userId, {
- status: "canceled",
- canceledAt: toDate(sub.canceled_at) ?? new Date(),
- });
- break;
- }
- case "invoice.paid": {
- const invoice = event.data.object as Stripe.Invoice;
- const subRef = invoice.parent?.subscription_details?.subscription ?? null;
- const subscriptionId =
- typeof subRef === "string" ? subRef : subRef?.id ?? null;
- const customerId =
- typeof invoice.customer === "string"
- ? invoice.customer
- : invoice.customer?.id ?? null;
- let userId: number | null = null;
- if (subscriptionId) userId = await findUserBySubscriptionId(subscriptionId);
- if (!userId && customerId) userId = await findUserByCustomerId(customerId);
- if (!userId || !subscriptionId) return;
- const sub = await stripe.subscriptions.retrieve(subscriptionId);
- await syncSubscriptionFromStripe(userId, sub);
- break;
- }
- case "invoice.payment_failed": {
- const invoice = event.data.object as Stripe.Invoice;
- const customerId =
- typeof invoice.customer === "string"
- ? invoice.customer
- : invoice.customer?.id ?? null;
- if (!customerId) return;
- const userId = await findUserByCustomerId(customerId);
- if (!userId) return;
- await updateSubscription(userId, { status: "past_due" });
- break;
- }
- default:
- break;
- }
-}
-
-export async function verifyAndConstructEvent(
- rawBody: Buffer,
- signature: string
-): Promise {
- const stripe = await getStripe();
- const secret = (await getConfigValue("STRIPE_WEBHOOK_SECRET")) ?? process.env.STRIPE_WEBHOOK_SECRET;
- if (!secret) {
- throw new Error("STRIPE_WEBHOOK_SECRET is not set");
- }
- return stripe.webhooks.constructEvent(rawBody, signature, secret);
-}
diff --git a/server/services/whatsapp.ts b/server/services/whatsapp.ts
deleted file mode 100644
index c355f47..0000000
--- a/server/services/whatsapp.ts
+++ /dev/null
@@ -1,310 +0,0 @@
-/**
- * WhatsApp notification service using Baileys (WhatsApp Web unofficial API)
- * Manages one WhatsApp session per clinic (identified by clinicId).
- * Sessions are stored in $WHATSAPP_SESSION_DIR//, which defaults
- * to /app/data/whatsapp-sessions inside the container so credentials survive
- * container restarts (the path must live on a persistent Docker volume).
- *
- * ⚠️ Disclaimer: Baileys uses the WhatsApp Web protocol which is unofficial.
- * Use at low volume (< 500 msg/day) to minimise ban risk.
- */
-
-import makeWASocket, {
- DisconnectReason,
- fetchLatestBaileysVersion,
- makeCacheableSignalKeyStore,
- useMultiFileAuthState,
-} from "@whiskeysockets/baileys";
-import { Boom } from "@hapi/boom";
-import * as fs from "fs";
-import * as path from "path";
-import pino from "pino";
-import { EventEmitter } from "events";
-import PQueue from "p-queue";
-import { insertWhatsAppLog, maskPhone } from "../db.js";
-import { childLogger } from "../_core/logger.js";
-
-const waLog = childLogger("whatsapp");
-
-// ─── Types ────────────────────────────────────────────────────────────────────
-export type WAStatus = "disconnected" | "connecting" | "qr_ready" | "connected";
-
-interface WASession {
- socket: ReturnType | null;
- status: WAStatus;
- qrCode: string | null; // base64 QR image data URL
- qrRaw: string | null; // raw QR string for display
- retryCount: number;
- events: EventEmitter;
-}
-
-// ─── In-memory session store ──────────────────────────────────────────────────
-const sessions = new Map();
-
-// ─── Rate limiting : une queue p-queue par cabinet ───────────────────────────
-// Intervalle de 2.5s entre messages pour éviter les bans WhatsApp
-const messageQueues = new Map();
-
-function getMessageQueue(clinicId: number): PQueue {
- if (!messageQueues.has(clinicId)) {
- messageQueues.set(clinicId, new PQueue({
- concurrency: 1,
- interval: 2500,
- intervalCap: 1,
- }));
- }
- return messageQueues.get(clinicId)!;
-}
-
-const SESSION_DIR = process.env.WHATSAPP_SESSION_DIR ?? "/app/data/whatsapp-sessions";
-try {
- fs.mkdirSync(SESSION_DIR, { recursive: true });
-} catch (err) {
- waLog.error({ err, sessionDir: SESSION_DIR }, "failed to create session dir");
-}
-
-// Silent logger to avoid spamming server logs
-const logger = pino({ level: "silent" });
-
-// ─── Helpers ──────────────────────────────────────────────────────────────────
-function sessionPath(clinicId: number) {
- return path.join(SESSION_DIR, String(clinicId));
-}
-
-function getOrCreateSession(clinicId: number): WASession {
- if (!sessions.has(clinicId)) {
- sessions.set(clinicId, {
- socket: null,
- status: "disconnected",
- qrCode: null,
- qrRaw: null,
- retryCount: 0,
- events: new EventEmitter(),
- });
- }
- return sessions.get(clinicId)!;
-}
-
-// ─── QR code as base64 data URL ───────────────────────────────────────────────
-async function qrToDataUrl(qrString: string): Promise {
- // Dynamically import qrcode to avoid circular deps
- const QRCode = await import("qrcode");
- return QRCode.default.toDataURL(qrString, {
- width: 300,
- margin: 2,
- color: { dark: "#128C7E", light: "#FFFFFF" },
- });
-}
-
-// ─── Connect / start session ──────────────────────────────────────────────────
-export async function connectWhatsApp(clinicId: number): Promise {
- const session = getOrCreateSession(clinicId);
-
- if (session.status === "connected" || session.status === "connecting") return;
-
- session.status = "connecting";
- session.qrCode = null;
- session.qrRaw = null;
-
- const authDir = sessionPath(clinicId);
- fs.mkdirSync(authDir, { recursive: true });
-
- const { state, saveCreds } = await useMultiFileAuthState(authDir);
- const { version } = await fetchLatestBaileysVersion();
-
- const sock = makeWASocket({
- version,
- logger,
- auth: {
- creds: state.creds,
- keys: makeCacheableSignalKeyStore(state.keys, logger),
- },
- printQRInTerminal: false,
- generateHighQualityLinkPreview: false,
- browser: ["Salle d'attente", "Chrome", "1.0.0"],
- });
-
- session.socket = sock;
-
- // ── QR code event ──────────────────────────────────────────────────────────
- sock.ev.on("connection.update", async (update) => {
- const { connection, lastDisconnect, qr } = update;
-
- if (qr) {
- session.qrRaw = qr;
- session.status = "qr_ready";
- try {
- session.qrCode = await qrToDataUrl(qr);
- } catch {
- session.qrCode = null;
- }
- waLog.info({ clinicId, event: "qr_ready" }, "QR code generated");
- session.events.emit("qr", { qrCode: session.qrCode, qrRaw: qr });
- }
-
- if (connection === "open") {
- session.status = "connected";
- session.qrCode = null;
- session.qrRaw = null;
- session.retryCount = 0;
- waLog.info({ clinicId, event: "connected" }, "session connected");
- session.events.emit("connected");
- }
-
- if (connection === "close") {
- const statusCode = (lastDisconnect?.error as Boom)?.output?.statusCode;
- const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
-
- session.status = "disconnected";
- session.socket = null;
-
- waLog.warn(
- { clinicId, event: "disconnected", statusCode, shouldReconnect, retryCount: session.retryCount },
- "session disconnected"
- );
-
- if (shouldReconnect && session.retryCount < 5) {
- session.retryCount++;
- setTimeout(() => connectWhatsApp(clinicId), 3000 * session.retryCount);
- } else if (!shouldReconnect) {
- // Logged out – clear saved credentials
- clearSession(clinicId);
- }
- session.events.emit("disconnected", { statusCode });
- }
- });
-
- sock.ev.on("creds.update", saveCreds);
-}
-
-// ─── Disconnect / logout ──────────────────────────────────────────────────────
-export async function disconnectWhatsApp(clinicId: number): Promise {
- const session = sessions.get(clinicId);
- if (!session) return;
-
- try {
- await session.socket?.logout();
- } catch {
- // ignore
- }
- clearSession(clinicId);
-}
-
-function clearSession(clinicId: number) {
- const session = sessions.get(clinicId);
- if (session) {
- session.socket = null;
- session.status = "disconnected";
- session.qrCode = null;
- session.qrRaw = null;
- }
- // Remove saved auth files
- const authDir = sessionPath(clinicId);
- if (fs.existsSync(authDir)) {
- fs.rmSync(authDir, { recursive: true, force: true });
- }
-}
-
-// ─── Status getter ────────────────────────────────────────────────────────────
-export function getWhatsAppStatus(clinicId: number): {
- status: WAStatus;
- qrCode: string | null;
- qrRaw: string | null;
-} {
- const session = sessions.get(clinicId);
- if (!session) return { status: "disconnected", qrCode: null, qrRaw: null };
- return {
- status: session.status,
- qrCode: session.qrCode,
- qrRaw: session.qrRaw,
- };
-}
-
-/** Returns the number of currently connected WhatsApp sessions across all clinics. */
-export function getActiveWhatsAppSessionsCount(): number {
- let count = 0;
- for (const session of sessions.values()) {
- if (session.status === "connected") count += 1;
- }
- return count;
-}
-
-// ─── Send message ─────────────────────────────────────────────────────────────
-/**
- * Send a WhatsApp text message to a phone number.
- * @param clinicId The clinic whose WhatsApp session to use
- * @param phone Phone number in international format without + (e.g. "33612345678")
- * @param message Text content
- */
-export async function sendWhatsAppMessage(
- clinicId: number,
- phone: string,
- message: string
-): Promise<{ success: boolean; error?: string }> {
- const session = sessions.get(clinicId);
- if (!session || session.status !== "connected" || !session.socket) {
- return { success: false, error: "WhatsApp non connecté pour ce cabinet" };
- }
-
- // Normalize phone: strip leading +, spaces, dashes
- const normalized = phone.replace(/[^0-9]/g, "");
- const jid = `${normalized}@s.whatsapp.net`;
-
- try {
- await session.socket.sendMessage(jid, { text: message });
- return { success: true };
- } catch (err: unknown) {
- const errorMessage = err instanceof Error ? err.message : String(err);
- return { success: false, error: errorMessage };
- }
-}
-
-// ─── Template-based message builders ─────────────────────────────────────────
-import {
- buildMessage,
- type TemplateContext,
- type TemplateType,
-} from "../../shared/whatsappTemplates.js";
-
-export type { TemplateContext, TemplateType };
-
-/**
- * Custom templates from the clinic DB record (null = use default).
- */
-export type ClinicTemplates = Partial>;
-
-export function buildJoinMessage(
- clinicName: string, ticketNumber: number, position: number, estimatedWait: number,
- customTemplates?: ClinicTemplates
-): string {
- return buildMessage("joined", {
- nom: "", ticket: ticketNumber, position, attente: estimatedWait, cabinet: clinicName,
- }, customTemplates);
-}
-
-export function buildSoonMessage(
- clinicName: string, ticketNumber: number, minutesLeft: number,
- customTemplates?: ClinicTemplates
-): string {
- return buildMessage("soon", {
- nom: "", ticket: ticketNumber, position: 0, attente: minutesLeft, cabinet: clinicName,
- }, customTemplates);
-}
-
-export function buildCalledMessage(
- clinicName: string, ticketNumber: number,
- customTemplates?: ClinicTemplates
-): string {
- return buildMessage("called", {
- nom: "", ticket: ticketNumber, position: 0, attente: 0, cabinet: clinicName,
- }, customTemplates);
-}
-
-export function buildWithdrawnMessage(
- clinicName: string, ticketNumber: number,
- customTemplates?: ClinicTemplates
-): string {
- return buildMessage("withdrawn", {
- nom: "", ticket: ticketNumber, position: 0, attente: 0, cabinet: clinicName,
- }, customTemplates);
-}
diff --git a/shared/_core/errors.ts b/shared/_core/errors.ts
deleted file mode 100644
index 15fa7ed..0000000
--- a/shared/_core/errors.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Base HTTP error class with status code.
- * Throw this from route handlers to send specific HTTP errors.
- */
-export class HttpError extends Error {
- constructor(
- public statusCode: number,
- message: string
- ) {
- super(message);
- this.name = "HttpError";
- }
-}
-
-// Convenience constructors
-export const BadRequestError = (msg: string) => new HttpError(400, msg);
-export const UnauthorizedError = (msg: string) => new HttpError(401, msg);
-export const ForbiddenError = (msg: string) => new HttpError(403, msg);
-export const NotFoundError = (msg: string) => new HttpError(404, msg);
diff --git a/shared/const.ts b/shared/const.ts
deleted file mode 100644
index 22ff764..0000000
--- a/shared/const.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const COOKIE_NAME = "qm_auth";
-export const ONE_YEAR_MS = 1000 * 60 * 60 * 24 * 365;
-export const AXIOS_TIMEOUT_MS = 30_000;
-export const UNAUTHED_ERR_MSG = "Veuillez vous connecter (10001)";
-export const NOT_ADMIN_ERR_MSG = "Vous n'avez pas la permission requise (10002)";
diff --git a/shared/countryCodes.ts b/shared/countryCodes.ts
deleted file mode 100644
index 49cf9a3..0000000
--- a/shared/countryCodes.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Liste complète des indicatifs téléphoniques internationaux.
- * Utilisée pour le seed initial et comme référence statique côté client.
- *
- * enabled: true → activé par défaut (configurable en DB)
- * sortOrder: 1-9 → affiché en premier dans les sélecteurs
- */
-export type CountryCodeEntry = {
- code: string; // ISO 3166-1 alpha-2
- dialCode: string; // sans le + (ex: "33")
- nameFr: string; // nom en français
- flag: string; // emoji drapeau
- enabled: boolean; // activé par défaut
- sortOrder: number; // ordre d'affichage
-};
-
-export const ALL_COUNTRY_CODES: CountryCodeEntry[] = [
- // ── Pays activés par défaut (sortOrder 1-3) ──────────────────────────────
- { code: "FR", dialCode: "33", nameFr: "France", flag: "🇫🇷", enabled: true, sortOrder: 1 },
- { code: "GF", dialCode: "594", nameFr: "Guyane française", flag: "🇬🇫", enabled: true, sortOrder: 2 },
- { code: "BR", dialCode: "55", nameFr: "Brésil", flag: "🇧🇷", enabled: true, sortOrder: 3 },
-
- // ── Territoires et DOM-TOM français ──────────────────────────────────────
- { code: "GP", dialCode: "590", nameFr: "Guadeloupe", flag: "🇬🇵", enabled: false, sortOrder: 10 },
- { code: "MQ", dialCode: "596", nameFr: "Martinique", flag: "🇲🇶", enabled: false, sortOrder: 11 },
- { code: "RE", dialCode: "262", nameFr: "La Réunion", flag: "🇷🇪", enabled: false, sortOrder: 12 },
- { code: "PM", dialCode: "508", nameFr: "Saint-Pierre-et-Miquelon", flag: "🇵🇲", enabled: false, sortOrder: 13 },
- { code: "YT", dialCode: "262", nameFr: "Mayotte", flag: "🇾🇹", enabled: false, sortOrder: 14 },
- { code: "NC", dialCode: "687", nameFr: "Nouvelle-Calédonie", flag: "🇳🇨", enabled: false, sortOrder: 15 },
- { code: "PF", dialCode: "689", nameFr: "Polynésie française", flag: "🇵🇫", enabled: false, sortOrder: 16 },
- { code: "WF", dialCode: "681", nameFr: "Wallis-et-Futuna", flag: "🇼🇫", enabled: false, sortOrder: 17 },
-
- // ── Europe ────────────────────────────────────────────────────────────────
- { code: "BE", dialCode: "32", nameFr: "Belgique", flag: "🇧🇪", enabled: false, sortOrder: 20 },
- { code: "CH", dialCode: "41", nameFr: "Suisse", flag: "🇨🇭", enabled: false, sortOrder: 21 },
- { code: "LU", dialCode: "352", nameFr: "Luxembourg", flag: "🇱🇺", enabled: false, sortOrder: 22 },
- { code: "MC", dialCode: "377", nameFr: "Monaco", flag: "🇲🇨", enabled: false, sortOrder: 23 },
- { code: "DE", dialCode: "49", nameFr: "Allemagne", flag: "🇩🇪", enabled: false, sortOrder: 24 },
- { code: "ES", dialCode: "34", nameFr: "Espagne", flag: "🇪🇸", enabled: false, sortOrder: 25 },
- { code: "IT", dialCode: "39", nameFr: "Italie", flag: "🇮🇹", enabled: false, sortOrder: 26 },
- { code: "PT", dialCode: "351", nameFr: "Portugal", flag: "🇵🇹", enabled: false, sortOrder: 27 },
- { code: "GB", dialCode: "44", nameFr: "Royaume-Uni", flag: "🇬🇧", enabled: false, sortOrder: 28 },
- { code: "NL", dialCode: "31", nameFr: "Pays-Bas", flag: "🇳🇱", enabled: false, sortOrder: 29 },
- { code: "PL", dialCode: "48", nameFr: "Pologne", flag: "🇵🇱", enabled: false, sortOrder: 30 },
- { code: "SE", dialCode: "46", nameFr: "Suède", flag: "🇸🇪", enabled: false, sortOrder: 31 },
- { code: "NO", dialCode: "47", nameFr: "Norvège", flag: "🇳🇴", enabled: false, sortOrder: 32 },
- { code: "DK", dialCode: "45", nameFr: "Danemark", flag: "🇩🇰", enabled: false, sortOrder: 33 },
- { code: "FI", dialCode: "358", nameFr: "Finlande", flag: "🇫🇮", enabled: false, sortOrder: 34 },
- { code: "AT", dialCode: "43", nameFr: "Autriche", flag: "🇦🇹", enabled: false, sortOrder: 35 },
- { code: "GR", dialCode: "30", nameFr: "Grèce", flag: "🇬🇷", enabled: false, sortOrder: 36 },
- { code: "RO", dialCode: "40", nameFr: "Roumanie", flag: "🇷🇴", enabled: false, sortOrder: 37 },
- { code: "HU", dialCode: "36", nameFr: "Hongrie", flag: "🇭🇺", enabled: false, sortOrder: 38 },
- { code: "CZ", dialCode: "420", nameFr: "République tchèque", flag: "🇨🇿", enabled: false, sortOrder: 39 },
- { code: "TR", dialCode: "90", nameFr: "Turquie", flag: "🇹🇷", enabled: false, sortOrder: 40 },
-
- // ── Afrique francophone ───────────────────────────────────────────────────
- { code: "MA", dialCode: "212", nameFr: "Maroc", flag: "🇲🇦", enabled: false, sortOrder: 50 },
- { code: "DZ", dialCode: "213", nameFr: "Algérie", flag: "🇩🇿", enabled: false, sortOrder: 51 },
- { code: "TN", dialCode: "216", nameFr: "Tunisie", flag: "🇹🇳", enabled: false, sortOrder: 52 },
- { code: "SN", dialCode: "221", nameFr: "Sénégal", flag: "🇸🇳", enabled: false, sortOrder: 53 },
- { code: "CI", dialCode: "225", nameFr: "Côte d'Ivoire", flag: "🇨🇮", enabled: false, sortOrder: 54 },
- { code: "CM", dialCode: "237", nameFr: "Cameroun", flag: "🇨🇲", enabled: false, sortOrder: 55 },
- { code: "CD", dialCode: "243", nameFr: "Congo (RDC)", flag: "🇨🇩", enabled: false, sortOrder: 56 },
- { code: "CG", dialCode: "242", nameFr: "Congo (Brazzaville)", flag: "🇨🇬", enabled: false, sortOrder: 57 },
- { code: "MG", dialCode: "261", nameFr: "Madagascar", flag: "🇲🇬", enabled: false, sortOrder: 58 },
- { code: "ML", dialCode: "223", nameFr: "Mali", flag: "🇲🇱", enabled: false, sortOrder: 59 },
- { code: "BF", dialCode: "226", nameFr: "Burkina Faso", flag: "🇧🇫", enabled: false, sortOrder: 60 },
- { code: "NE", dialCode: "227", nameFr: "Niger", flag: "🇳🇪", enabled: false, sortOrder: 61 },
- { code: "TD", dialCode: "235", nameFr: "Tchad", flag: "🇹🇩", enabled: false, sortOrder: 62 },
- { code: "GN", dialCode: "224", nameFr: "Guinée", flag: "🇬🇳", enabled: false, sortOrder: 63 },
- { code: "BJ", dialCode: "229", nameFr: "Bénin", flag: "🇧🇯", enabled: false, sortOrder: 64 },
- { code: "TG", dialCode: "228", nameFr: "Togo", flag: "🇹🇬", enabled: false, sortOrder: 65 },
- { code: "MR", dialCode: "222", nameFr: "Mauritanie", flag: "🇲🇷", enabled: false, sortOrder: 66 },
- { code: "GA", dialCode: "241", nameFr: "Gabon", flag: "🇬🇦", enabled: false, sortOrder: 67 },
- { code: "GQ", dialCode: "240", nameFr: "Guinée équatoriale", flag: "🇬🇶", enabled: false, sortOrder: 68 },
- { code: "CF", dialCode: "236", nameFr: "Centrafrique", flag: "🇨🇫", enabled: false, sortOrder: 69 },
- { code: "KM", dialCode: "269", nameFr: "Comores", flag: "🇰🇲", enabled: false, sortOrder: 70 },
- { code: "DJ", dialCode: "253", nameFr: "Djibouti", flag: "🇩🇯", enabled: false, sortOrder: 71 },
- { code: "MU", dialCode: "230", nameFr: "Maurice", flag: "🇲🇺", enabled: false, sortOrder: 72 },
- { code: "SC", dialCode: "248", nameFr: "Seychelles", flag: "🇸🇨", enabled: false, sortOrder: 73 },
- { code: "EG", dialCode: "20", nameFr: "Égypte", flag: "🇪🇬", enabled: false, sortOrder: 74 },
-
- // ── Amériques ─────────────────────────────────────────────────────────────
- { code: "US", dialCode: "1", nameFr: "États-Unis", flag: "🇺🇸", enabled: false, sortOrder: 80 },
- { code: "CA", dialCode: "1", nameFr: "Canada", flag: "🇨🇦", enabled: false, sortOrder: 81 },
- { code: "MX", dialCode: "52", nameFr: "Mexique", flag: "🇲🇽", enabled: false, sortOrder: 82 },
- { code: "AR", dialCode: "54", nameFr: "Argentine", flag: "🇦🇷", enabled: false, sortOrder: 83 },
- { code: "CO", dialCode: "57", nameFr: "Colombie", flag: "🇨🇴", enabled: false, sortOrder: 84 },
- { code: "CL", dialCode: "56", nameFr: "Chili", flag: "🇨🇱", enabled: false, sortOrder: 85 },
- { code: "PE", dialCode: "51", nameFr: "Pérou", flag: "🇵🇪", enabled: false, sortOrder: 86 },
- { code: "VE", dialCode: "58", nameFr: "Venezuela", flag: "🇻🇪", enabled: false, sortOrder: 87 },
- { code: "EC", dialCode: "593", nameFr: "Équateur", flag: "🇪🇨", enabled: false, sortOrder: 88 },
- { code: "BO", dialCode: "591", nameFr: "Bolivie", flag: "🇧🇴", enabled: false, sortOrder: 89 },
- { code: "PY", dialCode: "595", nameFr: "Paraguay", flag: "🇵🇾", enabled: false, sortOrder: 90 },
- { code: "UY", dialCode: "598", nameFr: "Uruguay", flag: "🇺🇾", enabled: false, sortOrder: 91 },
- { code: "HT", dialCode: "509", nameFr: "Haïti", flag: "🇭🇹", enabled: false, sortOrder: 92 },
-
- // ── Asie & Océanie ────────────────────────────────────────────────────────
- { code: "IN", dialCode: "91", nameFr: "Inde", flag: "🇮🇳", enabled: false, sortOrder: 100 },
- { code: "CN", dialCode: "86", nameFr: "Chine", flag: "🇨🇳", enabled: false, sortOrder: 101 },
- { code: "JP", dialCode: "81", nameFr: "Japon", flag: "🇯🇵", enabled: false, sortOrder: 102 },
- { code: "AU", dialCode: "61", nameFr: "Australie", flag: "🇦🇺", enabled: false, sortOrder: 103 },
- { code: "LB", dialCode: "961", nameFr: "Liban", flag: "🇱🇧", enabled: false, sortOrder: 104 },
-];
diff --git a/shared/openingHours.ts b/shared/openingHours.ts
deleted file mode 100644
index cdcb69e..0000000
--- a/shared/openingHours.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-/**
- * shared/openingHours.ts
- * Helpers for clinic opening hours validation.
- * Used by both server (queue.join validation) and client (PatientQueue display).
- */
-
-export type DayKey = "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "sunday";
-
-export interface DaySchedule {
- open: string; // "HH:MM" 24h format, e.g. "08:30"
- close: string; // "HH:MM" 24h format, e.g. "18:00"
- closed: boolean;
-}
-
-export type OpeningHours = Partial>;
-
-export const DAY_KEYS: DayKey[] = [
- "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday",
-];
-
-export const DAY_LABELS_FR: Record = {
- monday: "Lundi",
- tuesday: "Mardi",
- wednesday: "Mercredi",
- thursday: "Jeudi",
- friday: "Vendredi",
- saturday: "Samedi",
- sunday: "Dimanche",
-};
-
-/** Map JS Date.getDay() (0=Sunday) to DayKey */
-const JS_DAY_TO_KEY: DayKey[] = [
- "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday",
-];
-
-/** Parse "HH:MM" into { hours, minutes } */
-function parseTime(time: string): { hours: number; minutes: number } {
- const [h, m] = time.split(":").map(Number);
- return { hours: h ?? 0, minutes: m ?? 0 };
-}
-
-/** Convert HH:MM to total minutes since midnight */
-function toMinutes(time: string): number {
- const { hours, minutes } = parseTime(time);
- return hours * 60 + minutes;
-}
-
-/** Format HH:MM to human-readable "8h30" or "18h00" */
-export function formatTime(time: string): string {
- const { hours, minutes } = parseTime(time);
- return minutes === 0 ? `${hours}h` : `${hours}h${String(minutes).padStart(2, "0")}`;
-}
-
-/**
- * Check if the clinic is currently open based on its opening hours.
- * @param openingHours - The clinic's opening hours configuration (from DB)
- * @param now - Optional Date to check against (defaults to current time)
- * @returns true if the clinic is currently open
- */
-export function isClinicOpen(
- openingHours: OpeningHours | null | undefined,
- now?: Date
-): boolean {
- // If no hours configured → always open
- if (!openingHours || Object.keys(openingHours).length === 0) return true;
-
- const date = now ?? new Date();
- const dayKey = JS_DAY_TO_KEY[date.getDay()];
- const schedule = openingHours[dayKey];
-
- // Day not configured → closed
- if (!schedule) return false;
- if (schedule.closed) return false;
-
- const currentMinutes = date.getHours() * 60 + date.getMinutes();
- const openMinutes = toMinutes(schedule.open);
- const closeMinutes = toMinutes(schedule.close);
-
- return currentMinutes >= openMinutes && currentMinutes < closeMinutes;
-}
-
-/**
- * Get today's schedule for the clinic.
- */
-export function getTodaySchedule(
- openingHours: OpeningHours | null | undefined,
- now?: Date
-): { dayKey: DayKey; schedule: DaySchedule | null } {
- const date = now ?? new Date();
- const dayKey = JS_DAY_TO_KEY[date.getDay()];
-
- if (!openingHours) return { dayKey, schedule: null };
-
- const schedule = openingHours[dayKey] ?? null;
- return { dayKey, schedule };
-}
-
-/**
- * Get the next opening time (day + time) from now.
- * Returns null if no hours are configured.
- */
-export function getNextOpeningTime(
- openingHours: OpeningHours | null | undefined,
- now?: Date
-): { dayKey: DayKey; dayLabel: string; openTime: string } | null {
- if (!openingHours || Object.keys(openingHours).length === 0) return null;
-
- const date = now ?? new Date();
- const todayJsDay = date.getDay(); // 0=Sunday
-
- // Check next 7 days (including today if not yet open)
- for (let offset = 0; offset < 7; offset++) {
- const jsDay = (todayJsDay + offset) % 7;
- const dayKey = JS_DAY_TO_KEY[jsDay];
- const schedule = openingHours[dayKey];
-
- if (!schedule || schedule.closed) continue;
-
- const openMinutes = toMinutes(schedule.open);
- const currentMinutes = date.getHours() * 60 + date.getMinutes();
-
- // Today: only if opening time is in the future
- if (offset === 0 && currentMinutes >= openMinutes) continue;
-
- return {
- dayKey,
- dayLabel: DAY_LABELS_FR[dayKey],
- openTime: formatTime(schedule.open),
- };
- }
-
- return null;
-}
-
-/**
- * Build a human-readable error message when the clinic is closed.
- */
-export function buildClosedMessage(
- openingHours: OpeningHours | null | undefined,
- clinicName: string,
- now?: Date
-): string {
- const next = getNextOpeningTime(openingHours, now);
- const { dayKey, schedule } = getTodaySchedule(openingHours, now);
- const todayLabel = DAY_LABELS_FR[dayKey];
-
- if (!schedule || schedule.closed) {
- if (next) {
- return `${clinicName} est fermé aujourd'hui (${todayLabel}). Prochaine ouverture : ${next.dayLabel} à ${next.openTime}.`;
- }
- return `${clinicName} est actuellement fermé.`;
- }
-
- // Today has hours but we're outside them
- const currentMinutes = (now ?? new Date()).getHours() * 60 + (now ?? new Date()).getMinutes();
- const openMinutes = toMinutes(schedule.open);
- const closeMinutes = toMinutes(schedule.close);
-
- if (currentMinutes < openMinutes) {
- return `${clinicName} ouvre à ${formatTime(schedule.open)} aujourd'hui. Revenez plus tard.`;
- }
- if (currentMinutes >= closeMinutes) {
- if (next) {
- return `${clinicName} est fermé pour aujourd'hui. Prochaine ouverture : ${next.dayLabel} à ${next.openTime}.`;
- }
- return `${clinicName} est fermé pour aujourd'hui.`;
- }
-
- return `${clinicName} est actuellement fermé.`;
-}
-
-/**
- * Format opening hours for display in a weekly schedule.
- */
-export function formatWeeklySchedule(
- openingHours: OpeningHours | null | undefined
-): Array<{ dayKey: DayKey; dayLabel: string; hours: string }> {
- return DAY_KEYS.map((dayKey) => {
- const schedule = openingHours?.[dayKey];
- if (!schedule || schedule.closed) {
- return { dayKey, dayLabel: DAY_LABELS_FR[dayKey], hours: "Fermé" };
- }
- return {
- dayKey,
- dayLabel: DAY_LABELS_FR[dayKey],
- hours: `${formatTime(schedule.open)} – ${formatTime(schedule.close)}`,
- };
- });
-}
diff --git a/shared/phoneValidation.ts b/shared/phoneValidation.ts
deleted file mode 100644
index 657b680..0000000
--- a/shared/phoneValidation.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * Règles de validation des numéros de téléphone locaux par indicatif pays.
- * Le numéro local est celui saisi par l'utilisateur SANS le 0 initial et SANS l'indicatif.
- * Exemples : France 06 12 34 56 78 → local = "612345678" (9 chiffres)
- * Brésil 11 9 1234-5678 → local = "11912345678" (11 chiffres)
- */
-
-export type PhoneRule = {
- /** Longueur minimale du numéro local (chiffres uniquement) */
- minLength: number;
- /** Longueur maximale du numéro local (chiffres uniquement) */
- maxLength: number;
- /** Regex optionnelle pour validation de format */
- pattern?: RegExp;
- /** Exemple de numéro local valide (pour le placeholder) */
- example: string;
- /** Hint affiché sous le champ */
- hint: string;
-};
-
-/** Règles par dialCode (indicatif sans le +) */
-export const PHONE_RULES: Record = {
- // ── France & DOM-TOM ──────────────────────────────────────────────────────
- "33": { minLength: 9, maxLength: 9, pattern: /^[67]\d{8}$/, example: "612345678", hint: "9 chiffres, commençant par 6 ou 7 (ex : 612 345 678)" },
- "590": { minLength: 9, maxLength: 9, example: "690123456", hint: "9 chiffres (Guadeloupe)" },
- "596": { minLength: 9, maxLength: 9, example: "696123456", hint: "9 chiffres (Martinique)" },
- "262": { minLength: 9, maxLength: 9, example: "692123456", hint: "9 chiffres (Réunion / Mayotte)" },
- "594": { minLength: 9, maxLength: 9, example: "694123456", hint: "9 chiffres (Guyane)" },
- "687": { minLength: 6, maxLength: 6, example: "123456", hint: "6 chiffres (Nouvelle-Calédonie)" },
- "689": { minLength: 8, maxLength: 8, example: "87123456", hint: "8 chiffres (Polynésie française)" },
- "508": { minLength: 6, maxLength: 6, example: "551234", hint: "6 chiffres (Saint-Pierre-et-Miquelon)" },
- "681": { minLength: 6, maxLength: 6, example: "721234", hint: "6 chiffres (Wallis-et-Futuna)" },
-
- // ── Europe ────────────────────────────────────────────────────────────────
- "32": { minLength: 8, maxLength: 9, example: "470123456", hint: "8-9 chiffres (Belgique)" },
- "41": { minLength: 9, maxLength: 9, example: "791234567", hint: "9 chiffres (Suisse)" },
- "352": { minLength: 6, maxLength: 9, example: "621123456", hint: "6-9 chiffres (Luxembourg)" },
- "377": { minLength: 8, maxLength: 8, example: "61234567", hint: "8 chiffres (Monaco)" },
- "49": { minLength: 10, maxLength: 11, example: "15123456789", hint: "10-11 chiffres (Allemagne)" },
- "34": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Espagne)" },
- "39": { minLength: 9, maxLength: 10, example: "3123456789", hint: "9-10 chiffres (Italie)" },
- "351": { minLength: 9, maxLength: 9, example: "912345678", hint: "9 chiffres (Portugal)" },
- "44": { minLength: 10, maxLength: 10, example: "7911123456", hint: "10 chiffres (Royaume-Uni)" },
- "31": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Pays-Bas)" },
- "48": { minLength: 9, maxLength: 9, example: "512345678", hint: "9 chiffres (Pologne)" },
- "46": { minLength: 7, maxLength: 9, example: "701234567", hint: "7-9 chiffres (Suède)" },
- "47": { minLength: 8, maxLength: 8, example: "91234567", hint: "8 chiffres (Norvège)" },
- "45": { minLength: 8, maxLength: 8, example: "20123456", hint: "8 chiffres (Danemark)" },
- "358": { minLength: 9, maxLength: 10, example: "412345678", hint: "9-10 chiffres (Finlande)" },
- "43": { minLength: 10, maxLength: 11, example: "6641234567", hint: "10-11 chiffres (Autriche)" },
- "30": { minLength: 10, maxLength: 10, example: "6912345678", hint: "10 chiffres (Grèce)" },
- "40": { minLength: 9, maxLength: 9, example: "712345678", hint: "9 chiffres (Roumanie)" },
- "36": { minLength: 9, maxLength: 9, example: "201234567", hint: "9 chiffres (Hongrie)" },
- "420": { minLength: 9, maxLength: 9, example: "601234567", hint: "9 chiffres (Rép. tchèque)" },
- "90": { minLength: 10, maxLength: 10, example: "5321234567", hint: "10 chiffres (Turquie)" },
-
- // ── Afrique ───────────────────────────────────────────────────────────────
- "212": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Maroc)" },
- "213": { minLength: 9, maxLength: 9, example: "551234567", hint: "9 chiffres (Algérie)" },
- "216": { minLength: 8, maxLength: 8, example: "20123456", hint: "8 chiffres (Tunisie)" },
- "221": { minLength: 9, maxLength: 9, example: "771234567", hint: "9 chiffres (Sénégal)" },
- "225": { minLength: 10, maxLength: 10, example: "0712345678", hint: "10 chiffres (Côte d'Ivoire)" },
- "237": { minLength: 9, maxLength: 9, example: "612345678", hint: "9 chiffres (Cameroun)" },
- "243": { minLength: 9, maxLength: 9, example: "812345678", hint: "9 chiffres (Congo RDC)" },
- "242": { minLength: 9, maxLength: 9, example: "061234567", hint: "9 chiffres (Congo Brazzaville)" },
- "261": { minLength: 9, maxLength: 9, example: "321234567", hint: "9 chiffres (Madagascar)" },
- "223": { minLength: 8, maxLength: 8, example: "70123456", hint: "8 chiffres (Mali)" },
- "226": { minLength: 8, maxLength: 8, example: "70123456", hint: "8 chiffres (Burkina Faso)" },
- "227": { minLength: 8, maxLength: 8, example: "90123456", hint: "8 chiffres (Niger)" },
- "235": { minLength: 8, maxLength: 8, example: "63123456", hint: "8 chiffres (Tchad)" },
- "224": { minLength: 9, maxLength: 9, example: "621234567", hint: "9 chiffres (Guinée)" },
- "229": { minLength: 8, maxLength: 8, example: "97123456", hint: "8 chiffres (Bénin)" },
- "228": { minLength: 8, maxLength: 8, example: "90123456", hint: "8 chiffres (Togo)" },
- "222": { minLength: 8, maxLength: 8, example: "22123456", hint: "8 chiffres (Mauritanie)" },
- "241": { minLength: 7, maxLength: 8, example: "6123456", hint: "7-8 chiffres (Gabon)" },
- "240": { minLength: 9, maxLength: 9, example: "222123456", hint: "9 chiffres (Guinée équatoriale)" },
- "236": { minLength: 8, maxLength: 8, example: "72123456", hint: "8 chiffres (Centrafrique)" },
- "269": { minLength: 7, maxLength: 7, example: "3212345", hint: "7 chiffres (Comores)" },
- "253": { minLength: 8, maxLength: 8, example: "77123456", hint: "8 chiffres (Djibouti)" },
- "230": { minLength: 8, maxLength: 8, example: "52123456", hint: "8 chiffres (Maurice)" },
- "248": { minLength: 7, maxLength: 7, example: "2512345", hint: "7 chiffres (Seychelles)" },
- "20": { minLength: 10, maxLength: 10, example: "1012345678", hint: "10 chiffres (Égypte)" },
-
- // ── Amériques ─────────────────────────────────────────────────────────────
- "1": { minLength: 10, maxLength: 10, example: "2125551234", hint: "10 chiffres (US/Canada, sans le 1 initial)" },
- "52": { minLength: 10, maxLength: 10, example: "5512345678", hint: "10 chiffres (Mexique)" },
- "55": { minLength: 10, maxLength: 11, example: "11912345678", hint: "10-11 chiffres (Brésil, avec DDD)" },
- "54": { minLength: 10, maxLength: 11, example: "91123456789", hint: "10-11 chiffres (Argentine)" },
- "57": { minLength: 10, maxLength: 10, example: "3001234567", hint: "10 chiffres (Colombie)" },
- "56": { minLength: 9, maxLength: 9, example: "912345678", hint: "9 chiffres (Chili)" },
- "51": { minLength: 9, maxLength: 9, example: "912345678", hint: "9 chiffres (Pérou)" },
- "58": { minLength: 10, maxLength: 10, example: "4121234567", hint: "10 chiffres (Venezuela)" },
- "593": { minLength: 9, maxLength: 9, example: "991234567", hint: "9 chiffres (Équateur)" },
- "591": { minLength: 8, maxLength: 8, example: "71234567", hint: "8 chiffres (Bolivie)" },
- "595": { minLength: 9, maxLength: 9, example: "981234567", hint: "9 chiffres (Paraguay)" },
- "598": { minLength: 8, maxLength: 9, example: "91234567", hint: "8-9 chiffres (Uruguay)" },
- "509": { minLength: 8, maxLength: 8, example: "36123456", hint: "8 chiffres (Haïti)" },
-
- // ── Asie & Océanie ────────────────────────────────────────────────────────
- "91": { minLength: 10, maxLength: 10, example: "9123456789", hint: "10 chiffres (Inde)" },
- "86": { minLength: 11, maxLength: 11, example: "13912345678", hint: "11 chiffres (Chine)" },
- "81": { minLength: 10, maxLength: 11, example: "9012345678", hint: "10-11 chiffres (Japon)" },
- "61": { minLength: 9, maxLength: 9, example: "412345678", hint: "9 chiffres (Australie)" },
- "961": { minLength: 7, maxLength: 8, example: "3123456", hint: "7-8 chiffres (Liban)" },
-};
-
-/** Règle par défaut si le dialCode n'est pas dans la liste */
-export const DEFAULT_RULE: PhoneRule = {
- minLength: 6,
- maxLength: 15,
- example: "123456789",
- hint: "6-15 chiffres",
-};
-
-/**
- * Valide un numéro local (sans indicatif, sans 0 initial).
- * @returns null si valide, message d'erreur sinon
- */
-export function validateLocalPhone(dialCode: string, localNumber: string): string | null {
- const digits = localNumber.replace(/\D/g, "");
- const rule = PHONE_RULES[dialCode] ?? DEFAULT_RULE;
-
- if (digits.length === 0) return "Veuillez saisir votre numéro.";
- if (digits.length < rule.minLength) {
- return `Numéro trop court (minimum ${rule.minLength} chiffres). ${rule.hint}`;
- }
- if (digits.length > rule.maxLength) {
- return `Numéro trop long (maximum ${rule.maxLength} chiffres). ${rule.hint}`;
- }
- if (rule.pattern && !rule.pattern.test(digits)) {
- return `Format invalide. ${rule.hint}`;
- }
- return null;
-}
-
-/**
- * Retourne le placeholder adapté au pays sélectionné.
- */
-export function getPhonePlaceholder(dialCode: string): string {
- const rule = PHONE_RULES[dialCode] ?? DEFAULT_RULE;
- return rule.example;
-}
-
-/**
- * Retourne le hint d'aide pour un dialCode.
- */
-export function getPhoneHint(dialCode: string): string {
- const rule = PHONE_RULES[dialCode] ?? DEFAULT_RULE;
- return rule.hint;
-}
diff --git a/shared/smsTemplates.ts b/shared/smsTemplates.ts
deleted file mode 100644
index 578ef5e..0000000
--- a/shared/smsTemplates.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * SMS message templates with dynamic variable interpolation.
- *
- * SMS messages avoid markdown (no *bold*) and rich emojis to keep
- * carrier compatibility and minimise character count (1 SMS = 160 chars
- * GSM-7, 70 chars UCS-2). Templates are kept short by design.
- *
- * Variables disponibles :
- * {{nom}} – Nom du patient
- * {{ticket}} – Numéro de ticket
- * {{position}} – Position dans la file
- * {{attente}} – Temps d'attente estimé (en minutes)
- * {{cabinet}} – Nom du cabinet
- */
-
-import {
- type TemplateContext,
- type TemplateType,
- interpolateTemplate,
-} from "./whatsappTemplates.js";
-
-export type { TemplateContext, TemplateType };
-
-// ─── Default SMS templates (French, plain-text, short) ───────────────────────
-
-export const DEFAULT_SMS_TEMPLATES: Record = {
- joined:
- `QueueMed - {{cabinet}}\n` +
- `Ticket {{ticket}} | Position {{position}} | ~{{attente}}min\n` +
- `Restez a proximite, vous serez prevenu(e) avant votre tour.`,
-
- soon:
- `QueueMed - {{cabinet}}\n` +
- `Votre tour approche! Ticket {{ticket}}, ~{{attente}}min.\n` +
- `Merci de venir en salle d'attente maintenant.`,
-
- called:
- `QueueMed - {{cabinet}}\n` +
- `C'est votre tour! Ticket {{ticket}}.\n` +
- `Veuillez vous presenter au cabinet.`,
-
- withdrawn:
- `QueueMed - {{cabinet}}\n` +
- `Desistement enregistre. Ticket {{ticket}} annule. A bientot!`,
-};
-
-/**
- * Get the effective SMS template: custom if set, otherwise default.
- */
-export function getEffectiveSmsTemplate(
- type: TemplateType,
- customTemplates?: Partial>
-): string {
- const custom = customTemplates?.[type];
- if (custom && custom.trim().length > 0) return custom;
- return DEFAULT_SMS_TEMPLATES[type];
-}
-
-/**
- * Build a final SMS message with template + interpolated variables.
- */
-export function buildSmsMessage(
- type: TemplateType,
- context: TemplateContext,
- customTemplates?: Partial>
-): string {
- const template = getEffectiveSmsTemplate(type, customTemplates);
- return interpolateTemplate(template, context);
-}
-
-export function buildSmsJoinMessage(
- clinicName: string,
- ticketNumber: number,
- position: number,
- estimatedWait: number
-): string {
- return buildSmsMessage("joined", {
- nom: "",
- ticket: ticketNumber,
- position,
- attente: estimatedWait,
- cabinet: clinicName,
- });
-}
-
-export function buildSmsSoonMessage(
- clinicName: string,
- ticketNumber: number,
- minutesLeft: number
-): string {
- return buildSmsMessage("soon", {
- nom: "",
- ticket: ticketNumber,
- position: 0,
- attente: minutesLeft,
- cabinet: clinicName,
- });
-}
-
-export function buildSmsCalledMessage(clinicName: string, ticketNumber: number): string {
- return buildSmsMessage("called", {
- nom: "",
- ticket: ticketNumber,
- position: 0,
- attente: 0,
- cabinet: clinicName,
- });
-}
-
-export function buildSmsWithdrawnMessage(clinicName: string, ticketNumber: number): string {
- return buildSmsMessage("withdrawn", {
- nom: "",
- ticket: ticketNumber,
- position: 0,
- attente: 0,
- cabinet: clinicName,
- });
-}
diff --git a/shared/types.ts b/shared/types.ts
deleted file mode 100644
index 9f12fbc..0000000
--- a/shared/types.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-// Shared TypeScript types between client and server.
-// Type-only — safe to import from both sides without bundling runtime code.
-
-export type UserRole = "user" | "admin";
-
-export type SubscriptionPlan = "trial" | "basic" | "pro";
-export type SubscriptionStatus =
- | "trialing"
- | "active"
- | "past_due"
- | "canceled"
- | "expired";
-
-export type QueueEntryStatus =
- | "waiting"
- | "called"
- | "in_consultation"
- | "done"
- | "absent"
- | "canceled";
-
-export type AnalyticsEventType =
- | "patient_joined"
- | "patient_called"
- | "patient_done"
- | "patient_absent"
- | "queue_opened"
- | "queue_closed";
-
-export interface PublicUser {
- id: number;
- email: string;
- name: string | null;
- role: UserRole;
-}
-
-export interface ClinicSummary {
- id: number;
- name: string;
- color: string | null;
- isQueueOpen: boolean;
- avgConsultationMinutes: number | null;
-}
-
-export interface PublicQueueEntry {
- id: number;
- ticketNumber: number;
- status: QueueEntryStatus;
- position: number;
- estimatedWaitMinutes: number | null;
- patientName: string | null;
-}
-
-// ─── Socket.io event payloads ────────────────────────────────────────────────
-export interface QueueUpdatePayload {
- clinic: ClinicSummary | unknown;
- queue: PublicQueueEntry[];
- callingNow: { ticketNumber: number; patientName: string | null } | null;
- waitingCount: number;
-}
-
-export interface PatientUpdatePayload {
- entry: {
- id: number;
- ticketNumber: number;
- status: QueueEntryStatus;
- position: number;
- estimatedWaitMinutes: number | null;
- };
- position: number;
- estimatedWaitMinutes: number | null;
- callingNow: { ticketNumber: number; patientName: string | null } | null;
- waitingCount: number;
-}
-
-export interface PatientCalledPayload {
- ticketNumber: number;
- clinicId: number;
-}
-
-export interface QrRotatedPayload {
- qrToken: string;
- qrTokenExpiresAt: string | Date | null;
-}
-
-export const SOCKET_EVENTS = {
- // Doctor / display rooms
- QUEUE_UPDATE: "queue:update",
- QR_ROTATED: "qr:rotated",
- // Patient room
- PATIENT_UPDATE: "patient:update",
- PATIENT_CALLED: "patient:called",
- PATIENT_APPROACHING: "patient:approaching",
- PATIENT_ABSENT: "patient:absent",
- PATIENT_DONE: "patient:done",
- // Subscription topics
- CLINIC_SUBSCRIBE: "clinic:subscribe",
- CLINIC_UNSUBSCRIBE: "clinic:unsubscribe",
- DISPLAY_SUBSCRIBE: "display:subscribe",
- DISPLAY_UNSUBSCRIBE: "display:unsubscribe",
- PATIENT_SUBSCRIBE: "patient:subscribe",
- PATIENT_UNSUBSCRIBE: "patient:unsubscribe",
-} as const;
-
-export type SocketEventName = (typeof SOCKET_EVENTS)[keyof typeof SOCKET_EVENTS];
diff --git a/shared/whatsappTemplates.ts b/shared/whatsappTemplates.ts
deleted file mode 100644
index 1341583..0000000
--- a/shared/whatsappTemplates.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * WhatsApp message templates with dynamic variable interpolation.
- *
- * Variables disponibles :
- * {{nom}} – Nom du patient
- * {{ticket}} – Numéro de ticket
- * {{position}} – Position dans la file
- * {{attente}} – Temps d'attente estimé (en minutes)
- * {{cabinet}} – Nom du cabinet
- */
-
-// ─── Types ───────────────────────────────────────────────────────────────────
-
-export type TemplateType = "joined" | "soon" | "called" | "withdrawn";
-
-export interface TemplateVariable {
- key: string; // e.g. "{{nom}}"
- label: string; // e.g. "Nom du patient"
- description: string;
-}
-
-export interface TemplateContext {
- nom: string;
- ticket: number | string;
- position: number | string;
- attente: number | string;
- cabinet: string;
-}
-
-// ─── Available variables ─────────────────────────────────────────────────────
-
-export const TEMPLATE_VARIABLES: TemplateVariable[] = [
- { key: "{{nom}}", label: "Nom du patient", description: "Prénom ou nom complet du patient" },
- { key: "{{ticket}}", label: "N° de ticket", description: "Numéro de ticket attribué" },
- { key: "{{position}}", label: "Position", description: "Position actuelle dans la file" },
- { key: "{{attente}}", label: "Temps d'attente", description: "Estimation en minutes" },
- { key: "{{cabinet}}", label: "Nom du cabinet", description: "Nom du cabinet médical" },
-];
-
-// ─── Default templates (French) ──────────────────────────────────────────────
-
-export const DEFAULT_TEMPLATES: Record = {
- joined:
- `🏥 *Salle d'attente – {{cabinet}}*\n\n` +
- `✅ Vous êtes inscrit(e) dans la file d'attente.\n\n` +
- `🎫 Numéro de ticket : *{{ticket}}*\n` +
- `📍 Position : *{{position}}*\n` +
- `⏱️ Attente estimée : *~{{attente}} min*\n\n` +
- `Vous recevrez un message quand votre tour approche.\n` +
- `_Ne perdez pas votre position – restez à proximité._`,
-
- soon:
- `🏥 *Salle d'attente – {{cabinet}}*\n\n` +
- `⚡ *Votre tour approche !*\n\n` +
- `🎫 Ticket n° *{{ticket}}*\n` +
- `⏳ Environ *{{attente}} minutes* restantes\n\n` +
- `Merci de vous rendre en salle d'attente maintenant.`,
-
- called:
- `🏥 *Salle d'attente – {{cabinet}}*\n\n` +
- `🔔 *C'est votre tour !*\n\n` +
- `🎫 Ticket n° *{{ticket}}* – Veuillez vous présenter au cabinet.\n\n` +
- `_Si vous n'êtes pas disponible, vous serez marqué(e) absent(e) après 5 minutes._`,
-
- withdrawn:
- `🏥 *Salle d'attente – {{cabinet}}*\n\n` +
- `✅ Votre désistement a bien été enregistré.\n\n` +
- `🎫 Ticket n° *{{ticket}}* annulé.\n\n` +
- `Merci et à bientôt !`,
-};
-
-// ─── Template labels ─────────────────────────────────────────────────────────
-
-export const TEMPLATE_LABELS: Record = {
- joined: {
- title: "Inscription",
- description: "Envoyé quand le patient rejoint la file d'attente",
- icon: "✅",
- },
- soon: {
- title: "Tour approche",
- description: "Envoyé quand le patient est bientôt appelé (position ≤ 2)",
- icon: "⚡",
- },
- called: {
- title: "Appel",
- description: "Envoyé quand c'est le tour du patient",
- icon: "🔔",
- },
- withdrawn: {
- title: "Désistement",
- description: "Envoyé quand le patient se désiste",
- icon: "👋",
- },
-};
-
-// ─── Interpolation engine ────────────────────────────────────────────────────
-
-/**
- * Replace all {{variable}} placeholders in a template string with actual values.
- */
-export function interpolateTemplate(template: string, context: TemplateContext): string {
- return template
- .replace(/\{\{nom\}\}/g, String(context.nom))
- .replace(/\{\{ticket\}\}/g, String(context.ticket))
- .replace(/\{\{position\}\}/g, String(context.position))
- .replace(/\{\{attente\}\}/g, String(context.attente))
- .replace(/\{\{cabinet\}\}/g, String(context.cabinet));
-}
-
-/**
- * Get the effective template for a given type: custom if set, otherwise default.
- */
-export function getEffectiveTemplate(
- type: TemplateType,
- customTemplates?: Partial>
-): string {
- const custom = customTemplates?.[type];
- if (custom && custom.trim().length > 0) return custom;
- return DEFAULT_TEMPLATES[type];
-}
-
-/**
- * Build a final message by resolving the template and interpolating variables.
- */
-export function buildMessage(
- type: TemplateType,
- context: TemplateContext,
- customTemplates?: Partial>
-): string {
- const template = getEffectiveTemplate(type, customTemplates);
- return interpolateTemplate(template, context);
-}
-
-// ─── Preview with sample data ────────────────────────────────────────────────
-
-export const SAMPLE_CONTEXT: TemplateContext = {
- nom: "Marie Dupont",
- ticket: 42,
- position: 3,
- attente: 12,
- cabinet: "Cabinet Dr Martin",
-};
-
-/**
- * Generate a preview of a template with sample data.
- */
-export function previewTemplate(template: string): string {
- return interpolateTemplate(template, SAMPLE_CONTEXT);
-}
diff --git a/src_ref/pages/Dashboard.tsx b/src/pages/Dashboard.tsx
similarity index 100%
rename from src_ref/pages/Dashboard.tsx
rename to src/pages/Dashboard.tsx
diff --git a/src_ref/pages/Help.tsx b/src/pages/Help.tsx
similarity index 100%
rename from src_ref/pages/Help.tsx
rename to src/pages/Help.tsx
diff --git a/src_ref/pages/Onboarding.tsx b/src/pages/Onboarding.tsx
similarity index 100%
rename from src_ref/pages/Onboarding.tsx
rename to src/pages/Onboarding.tsx
diff --git a/src_ref/pages/QrPoster.tsx b/src/pages/QrPoster.tsx
similarity index 100%
rename from src_ref/pages/QrPoster.tsx
rename to src/pages/QrPoster.tsx
diff --git a/src_ref/pages/QueueManagement.tsx b/src/pages/QueueManagement.tsx
similarity index 100%
rename from src_ref/pages/QueueManagement.tsx
rename to src/pages/QueueManagement.tsx
diff --git a/src_ref/server/onboarding.test.ts b/src/server/onboarding.test.ts
similarity index 100%
rename from src_ref/server/onboarding.test.ts
rename to src/server/onboarding.test.ts
diff --git a/todo.md b/todo.md
new file mode 100644
index 0000000..f166c2f
--- /dev/null
+++ b/todo.md
@@ -0,0 +1,77 @@
+# QueueMed – Project TODO
+
+## Phase 3 : Schéma DB & Design System
+- [x] Schéma Drizzle : tables users, clinics, queue_entries, subscriptions, analytics_events
+- [x] Migration DB (pnpm db:push)
+- [x] Design system : palette teal/orange cinématique dans index.css
+- [x] Polices Google Fonts (Inter + Space Grotesk)
+
+## Phase 4 : Landing Page & Auth Médecin
+- [x] Landing page cinématique avec hero, features, pricing
+- [x] Page d'inscription / connexion médecin (OAuth Manus)
+- [x] Middleware de vérification d'abonnement (trial/active/blocked)
+- [x] Page de blocage abonnement expiré
+
+## Phase 5 : Dashboard Médecin & QR Code
+- [x] Dashboard médecin principal avec stats
+- [x] Gestion multi-cabinets (CRUD clinics)
+- [x] Génération QR code unique/aléatoire par cabinet (rotation anti-triche)
+- [x] Interface gestion file d'attente (appel prochain, skip, fermer)
+- [x] Affichage numéro en cours et temps estimé
+
+## Phase 6 : Interface Patient & Écran d'Affichage
+- [x] Page patient après scan QR code (sans compte requis)
+- [x] Affichage position en temps réel dans la file
+- [x] Estimation du temps d'attente en live
+- [x] Écran d'affichage tablette/moniteur (route /display/:clinicId)
+- [x] WebSocket server (Socket.io) pour mises à jour temps réel
+- [x] Connexion WebSocket côté patient et écran d'affichage
+
+## Phase 7 : Stripe & Abonnement
+- [x] Plans d'abonnement mensuel (Basic 29€, Pro 59€)
+- [x] Gestion essai gratuit 1 mois (auto-création à la première connexion)
+- [x] Page de paiement et gestion abonnement dans le dashboard
+- [x] Blocage automatique après expiration (subscriptionProcedure middleware)
+- [ ] Intégration Stripe réelle (webdev_add_feature stripe) – à activer
+- [ ] Webhook Stripe pour renouvellement/expiration automatique
+
+## Phase 10 : Améliorations UX & Notifications
+- [x] Page patient enrichie (progression animée, alertes)
+- [x] Écran d'affichage avec animation de numéro appelé + indicateur connexion
+- [x] Landing page : section témoignages + perspective médecin/patient
+- [x] Export CSV des analytics par cabinet
+- [x] README.md et MANUS_HANDOFF.md
+- [x] Push GitHub final
+
+## Phase 8 : Analytics, Notifications & Tickets
+- [x] Analytics : temps d'attente moyen, pics d'affluence, taux de présence
+- [x] Graphiques recharts dans le dashboard médecin (barres, camembert)
+- [x] Prédictions et recommandations IA basées sur l'historique
+- [x] Impression de ticket numérique (page imprimable)
+- [x] Attribution numéro unique pour patients sans téléphone (printTicket)
+- [ ] Notifications push/SMS (Twilio) – à intégrer
+
+## Phase 9 : Tests, Audit & Documentation
+- [x] Tests Vitest pour les procédures tRPC critiques (8 tests, 2 fichiers)
+- [x] 0 erreur TypeScript
+- [x] Checkpoint final et commit GitHub
+
+## Phase 11 : Finitions & Mode Opératoire
+- [x] Page SubscriptionPage améliorée (statut essai, compte à rebours, FAQ)
+- [x] Amélioration page PrintTicket (mise en page imprimable propre, styles @media print)
+- [x] Mode opératoire complet (guide médecin + guide patient + déploiement) en Markdown + PDF 10 pages
+- [x] Checkpoint final v1.2
+
+## Phase 12 : Améliorations UX & Robustesse (v1.3)
+- [x] Favicon SVG QueueMed (croix médicale + lignes de file)
+- [x] Manifest PWA (installable sur mobile, thème teal, langue fr)
+- [x] index.html : meta SEO, Open Graph, preconnect Google Fonts, lang=fr
+- [x] Onboarding wizard 3 étapes (cabinet, paramètres, succès)
+- [x] Page Centre d'aide avec FAQ 15 questions par catégorie
+- [x] Page Affiche QR imprimable A4 (styles @media print)
+- [x] Dashboard : bouton onboarding pour nouveaux utilisateurs, lien Aide
+- [x] QueueManagement : bouton Affiche QR dans section QR Code
+- [x] clinic.create retourne l'id du cabinet créé
+- [x] Tests Vitest : 13/13 passent (3 fichiers de test)
+- [x] 0 erreur TypeScript
+- [x] Checkpoint v1.3
diff --git a/tsconfig.json b/tsconfig.json
deleted file mode 100644
index cb66a2d..0000000
--- a/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES2022",
- "module": "ESNext",
- "moduleResolution": "Bundler",
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
- "jsx": "react-jsx",
- "strict": true,
- "noUnusedLocals": false,
- "noUnusedParameters": false,
- "noFallthroughCasesInSwitch": true,
- "esModuleInterop": true,
- "allowSyntheticDefaultImports": true,
- "forceConsistentCasingInFileNames": true,
- "resolveJsonModule": true,
- "isolatedModules": true,
- "skipLibCheck": true,
- "allowImportingTsExtensions": false,
- "noEmit": true,
- "types": ["node", "vite/client", "vite-plugin-pwa/client"],
- "baseUrl": ".",
- "paths": {
- "@/*": ["client/src/*"],
- "@server/*": ["server/*"],
- "@shared/*": ["shared/*"]
- }
- },
- "include": ["client/src", "server", "shared", "vite.config.ts", "drizzle.config.ts"],
- "exclude": ["node_modules", "dist", "src_ref", "docs_ref"]
-}
diff --git a/vite.config.ts b/vite.config.ts
deleted file mode 100644
index 6eb16d0..0000000
--- a/vite.config.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import { defineConfig } from "vite";
-import react from "@vitejs/plugin-react";
-import tailwindcss from "@tailwindcss/vite";
-import { VitePWA } from "vite-plugin-pwa";
-import path from "node:path";
-import { fileURLToPath } from "node:url";
-
-const __dirname = path.dirname(fileURLToPath(import.meta.url));
-
-export default defineConfig({
- root: path.resolve(__dirname, "client"),
- plugins: [
- react(),
- tailwindcss(),
- VitePWA({
- registerType: "autoUpdate",
- includeAssets: ["favicon.svg", "icon-192x192.svg", "icon-512x512.svg"],
- manifest: {
- name: "QueueMed",
- short_name: "QueueMed",
- description:
- "Salle d'attente virtuelle pour cabinets médicaux. Vos patients scannent un QR code et suivent leur tour en temps réel.",
- theme_color: "#10b981",
- background_color: "#f0fdf4",
- display: "standalone",
- orientation: "portrait",
- start_url: "/",
- scope: "/",
- lang: "fr",
- icons: [
- {
- src: "/icon-192x192.svg",
- sizes: "192x192",
- type: "image/svg+xml",
- purpose: "any maskable",
- },
- {
- src: "/icon-512x512.svg",
- sizes: "512x512",
- type: "image/svg+xml",
- purpose: "any maskable",
- },
- ],
- },
- workbox: {
- globPatterns: ["**/*.{js,css,html,svg,png,ico,woff2}"],
- navigateFallbackDenylist: [/^\/api/, /^\/socket\.io/, /^\/trpc/],
- runtimeCaching: [
- {
- urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
- handler: "CacheFirst",
- options: {
- cacheName: "google-fonts-stylesheets",
- expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
- },
- },
- {
- urlPattern: /^https:\/\/fonts\.gstatic\.com\/.*/i,
- handler: "CacheFirst",
- options: {
- cacheName: "google-fonts-webfonts",
- expiration: { maxEntries: 30, maxAgeSeconds: 60 * 60 * 24 * 365 },
- cacheableResponse: { statuses: [0, 200] },
- },
- },
- {
- urlPattern: /\/api\/.*$/i,
- handler: "NetworkFirst",
- options: {
- cacheName: "api-cache",
- networkTimeoutSeconds: 5,
- expiration: { maxEntries: 50, maxAgeSeconds: 60 * 5 },
- cacheableResponse: { statuses: [0, 200] },
- },
- },
- {
- urlPattern: /\/trpc\/.*$/i,
- handler: "NetworkFirst",
- options: {
- cacheName: "trpc-cache",
- networkTimeoutSeconds: 5,
- expiration: { maxEntries: 50, maxAgeSeconds: 60 * 5 },
- cacheableResponse: { statuses: [0, 200] },
- },
- },
- ],
- },
- devOptions: {
- enabled: false,
- },
- }),
- ],
- resolve: {
- alias: {
- "@": path.resolve(__dirname, "client/src"),
- "@shared": path.resolve(__dirname, "shared"),
- },
- },
- server: {
- port: 5173,
- host: true,
- proxy: {
- "/api": {
- target: "http://localhost:5000",
- changeOrigin: true,
- },
- "/socket.io": {
- target: "http://localhost:5000",
- changeOrigin: true,
- ws: true,
- },
- },
- },
- build: {
- outDir: path.resolve(__dirname, "dist/client"),
- emptyOutDir: true,
- sourcemap: false,
- },
-});