diff --git a/.cursor/settings.json b/.cursor/settings.json
new file mode 100644
index 0000000..54ec55a
--- /dev/null
+++ b/.cursor/settings.json
@@ -0,0 +1,7 @@
+{
+ "plugins": {
+ "supabase": {
+ "enabled": true
+ }
+ }
+}
diff --git a/.dev.vars.example b/.dev.vars.example
new file mode 100644
index 0000000..7527660
--- /dev/null
+++ b/.dev.vars.example
@@ -0,0 +1,8 @@
+# Copy to .dev.vars for local `npm run preview` (Workers runtime)
+# Do not commit .dev.vars
+
+NEXTJS_ENV=development
+
+# Optional: mirror .env.local for preview (NEXT_PUBLIC_* are inlined at build time)
+# NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
+# NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
diff --git a/.env.local.example b/.env.local.example
new file mode 100644
index 0000000..946bd2c
--- /dev/null
+++ b/.env.local.example
@@ -0,0 +1,17 @@
+NEXT_PUBLIC_SUPABASE_URL=https://vcxpcyafnlyiyqmapyyy.supabase.co
+
+# Use EITHER publishable (sb_publishable_...) OR legacy anon JWT (eyJ...)
+# Dashboard → Project Settings → API
+NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-or-publishable-key
+
+# Auth: Dashboard → Authentication → URL configuration
+# Site URL: http://localhost:3000
+# Redirect URLs (include password reset):
+# http://localhost:3000/**
+# http://localhost:3000/auth/callback
+# http://localhost:3000/reset-password
+
+# For CLI migrations (IPv4 pooler — required if db push fails with IPv6 error)
+# Dashboard → Connect → Session mode (port 5432)
+SUPABASE_DB_PASSWORD=your-database-password
+SUPABASE_DB_URL=postgresql://postgres.vcxpcyafnlyiyqmapyyy:YOUR_PASSWORD@aws-0-YOUR_REGION.pooler.supabase.com:5432/postgres
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..54c6917
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+*.sh text eol=lf
+*.mjs text eol=lf
+*.sql text eol=lf
diff --git a/.github/workflows/deploy-cloudflare.yml b/.github/workflows/deploy-cloudflare.yml
new file mode 100644
index 0000000..468c7ea
--- /dev/null
+++ b/.github/workflows/deploy-cloudflare.yml
@@ -0,0 +1,29 @@
+name: Deploy to Cloudflare Workers
+
+on:
+ push:
+ branches: [main, master]
+ workflow_dispatch:
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: npm
+
+ - run: npm ci
+
+ - name: Build and deploy
+ run: npm run deploy
+ env:
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+ NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
+ NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c5bd586
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,49 @@
+# dependencies
+/node_modules
+/.pnp
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/versions
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# env files
+.env*.local
+.env
+
+# supabase CLI (keep project-ref for linked remote)
+supabase/.temp/*
+!supabase/.temp/project-ref
+
+# vercel
+.vercel
+
+# cloudflare / opennext
+.open-next
+.dev.vars
+.wrangler
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/actions/leagues.ts b/actions/leagues.ts
new file mode 100644
index 0000000..8d26774
--- /dev/null
+++ b/actions/leagues.ts
@@ -0,0 +1,77 @@
+"use server";
+
+import { revalidatePath } from "next/cache";
+import { createClient } from "@/lib/supabase/server";
+import * as leagues from "@/lib/services/leagues";
+import * as teams from "@/lib/services/teams";
+
+export async function createLeague(formData: FormData) {
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) throw new Error("Unauthorized");
+
+ const league = await leagues.createLeague(supabase, user.id, {
+ name: formData.get("name") as string,
+ description: (formData.get("description") as string) || undefined,
+ });
+
+ revalidatePath("/leagues");
+ return league;
+}
+
+export async function createCompetition(leagueId: string, formData: FormData) {
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) throw new Error("Unauthorized");
+
+ const data = await leagues.createCompetition(supabase, user.id, leagueId, {
+ name: formData.get("name") as string,
+ tournament_mode: formData.get("tournament_mode") as "league" | "cup",
+ timezone: (formData.get("timezone") as string) || "UTC",
+ });
+
+ revalidatePath(`/leagues/${leagueId}`);
+ return data;
+}
+
+export async function activateCompetition(competitionId: string) {
+ const supabase = await createClient();
+ await leagues.activateCompetition(supabase, competitionId);
+ revalidatePath("/leagues");
+}
+
+export async function generateFixtures(competitionId: string, mode: string) {
+ const supabase = await createClient();
+ await leagues.generateFixtures(
+ supabase,
+ competitionId,
+ mode as "league" | "cup"
+ );
+ revalidatePath("/leagues");
+}
+
+export async function createTeam(competitionId: string, formData: FormData) {
+ const supabase = await createClient();
+ const data = await teams.createTeam(supabase, competitionId, {
+ name: formData.get("name") as string,
+ nickname: (formData.get("nickname") as string) || undefined,
+ icon: (formData.get("icon") as string) || undefined,
+ });
+ revalidatePath("/leagues");
+ return data;
+}
+
+export async function saveLeagueRules(leagueId: string, rules: object) {
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) throw new Error("Unauthorized");
+
+ await leagues.saveLeagueRules(supabase, user.id, leagueId, rules);
+ revalidatePath(`/leagues/${leagueId}/rules`);
+}
diff --git a/actions/matches.ts b/actions/matches.ts
new file mode 100644
index 0000000..ad9d522
--- /dev/null
+++ b/actions/matches.ts
@@ -0,0 +1,51 @@
+"use server";
+
+import { revalidatePath } from "next/cache";
+import { createClient } from "@/lib/supabase/server";
+import * as matches from "@/lib/services/matches";
+
+export async function proposeSchedule(matchId: string, scheduledAt: string) {
+ const supabase = await createClient();
+ await matches.proposeSchedule(supabase, matchId, scheduledAt);
+ revalidatePath("/leagues");
+}
+
+export async function signSchedule(matchId: string, teamId: string) {
+ const supabase = await createClient();
+ await matches.signSchedule(supabase, matchId, teamId);
+ revalidatePath("/leagues");
+}
+
+export async function submitResult(
+ matchId: string,
+ teamId: string,
+ homeScore: number,
+ awayScore: number
+) {
+ const supabase = await createClient();
+ await matches.submitResult(supabase, matchId, teamId, homeScore, awayScore);
+ revalidatePath("/leagues");
+}
+
+export async function approveResult(matchId: string) {
+ const supabase = await createClient();
+ await matches.approveResult(supabase, matchId);
+ revalidatePath("/leagues");
+}
+
+export async function setResultByManager(
+ matchId: string,
+ homeScore: number,
+ awayScore: number,
+ note?: string
+) {
+ const supabase = await createClient();
+ await matches.setResultByManager(
+ supabase,
+ matchId,
+ homeScore,
+ awayScore,
+ note
+ );
+ revalidatePath("/leagues");
+}
diff --git a/actions/players.ts b/actions/players.ts
new file mode 100644
index 0000000..6efca96
--- /dev/null
+++ b/actions/players.ts
@@ -0,0 +1,39 @@
+"use server";
+
+import { revalidatePath } from "next/cache";
+import { createClient } from "@/lib/supabase/server";
+import * as players from "@/lib/services/players";
+
+export async function createPlayer(formData: FormData) {
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) throw new Error("Unauthorized");
+
+ await players.createPlayer(supabase, user.id, {
+ display_name: formData.get("display_name") as string,
+ external_id: (formData.get("external_id") as string) || undefined,
+ });
+
+ revalidatePath("/players");
+}
+
+export async function updatePlayerStatus(
+ playerId: string,
+ status: "active" | "inactive"
+) {
+ const supabase = await createClient();
+ await players.updatePlayerStatus(supabase, playerId, status);
+ revalidatePath("/players");
+}
+
+export async function togglePlayerStatus(
+ playerId: string,
+ currentStatus: string
+) {
+ await updatePlayerStatus(
+ playerId,
+ currentStatus === "active" ? "inactive" : "active"
+ );
+}
diff --git a/actions/teams.ts b/actions/teams.ts
new file mode 100644
index 0000000..01f2fd6
--- /dev/null
+++ b/actions/teams.ts
@@ -0,0 +1,64 @@
+"use server";
+
+import { revalidatePath } from "next/cache";
+import { createClient } from "@/lib/supabase/server";
+import * as teams from "@/lib/services/teams";
+import * as players from "@/lib/services/players";
+
+export async function updateTeamProfile(
+ teamId: string,
+ data: { home_stadium_name?: string; logo_path?: string }
+) {
+ const supabase = await createClient();
+ await teams.updateTeam(supabase, teamId, data);
+ revalidatePath("/leagues");
+}
+
+export async function setTeamAvailability(
+ teamId: string,
+ windows: { day_of_week: number; start_time?: string; end_time?: string }[]
+) {
+ const supabase = await createClient();
+ await teams.setAvailability(supabase, teamId, windows);
+ revalidatePath("/leagues");
+}
+
+export async function addToRoster(
+ teamId: string,
+ competitionId: string,
+ playerId: string
+) {
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) throw new Error("Unauthorized");
+
+ await players.addToRoster(supabase, user.id, {
+ teamId,
+ competitionId,
+ playerId,
+ });
+ revalidatePath("/leagues");
+}
+
+export async function registerTransfer(
+ competitionId: string,
+ playerId: string,
+ fromTeamId: string,
+ toTeamId: string
+) {
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) throw new Error("Unauthorized");
+
+ await players.registerTransfer(supabase, user.id, {
+ competitionId,
+ playerId,
+ fromTeamId,
+ toTeamId,
+ });
+ revalidatePath("/leagues");
+}
diff --git a/app/(auth)/forgot-password/manager/page.tsx b/app/(auth)/forgot-password/manager/page.tsx
new file mode 100644
index 0000000..4290a98
--- /dev/null
+++ b/app/(auth)/forgot-password/manager/page.tsx
@@ -0,0 +1,19 @@
+import { LoginPageShell } from "@/components/auth/login-form";
+import { ForgotPasswordForm } from "@/components/auth/forgot-password-form";
+import { YaltopiaFooter } from "@/components/layout/YaltopiaFooter";
+
+export default function ManagerForgotPasswordPage() {
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/app/(auth)/forgot-password/master/page.tsx b/app/(auth)/forgot-password/master/page.tsx
new file mode 100644
index 0000000..c4ddf21
--- /dev/null
+++ b/app/(auth)/forgot-password/master/page.tsx
@@ -0,0 +1,19 @@
+import { LoginPageShell } from "@/components/auth/login-form";
+import { ForgotPasswordForm } from "@/components/auth/forgot-password-form";
+import { YaltopiaFooter } from "@/components/layout/YaltopiaFooter";
+
+export default function MasterForgotPasswordPage() {
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/app/(auth)/login/manager/page.tsx b/app/(auth)/login/manager/page.tsx
new file mode 100644
index 0000000..1489e25
--- /dev/null
+++ b/app/(auth)/login/manager/page.tsx
@@ -0,0 +1,34 @@
+import Link from "next/link";
+import { LoginForm, LoginPageShell } from "@/components/auth/login-form";
+import { YaltopiaFooter } from "@/components/layout/YaltopiaFooter";
+
+export default function ManagerLoginPage() {
+ return (
+ <>
+
+ No account?{" "}
+
+ Create account
+
+ {" · "}
+
+ Home
+
+
+ }
+ >
+
+
+
+
+
+ >
+ );
+}
diff --git a/app/(auth)/login/master/page.tsx b/app/(auth)/login/master/page.tsx
new file mode 100644
index 0000000..765689b
--- /dev/null
+++ b/app/(auth)/login/master/page.tsx
@@ -0,0 +1,29 @@
+import Link from "next/link";
+import { LoginForm, LoginPageShell } from "@/components/auth/login-form";
+import { YaltopiaFooter } from "@/components/layout/YaltopiaFooter";
+
+export default function MasterLoginPage() {
+ return (
+ <>
+
+
+ Create master account
+
+
+ }
+ >
+
+
+
+
+
+ >
+ );
+}
diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx
new file mode 100644
index 0000000..653be9c
--- /dev/null
+++ b/app/(auth)/login/page.tsx
@@ -0,0 +1,5 @@
+import { redirect } from "next/navigation";
+
+export default function LoginPage() {
+ redirect("/");
+}
diff --git a/app/(auth)/reset-password/page.tsx b/app/(auth)/reset-password/page.tsx
new file mode 100644
index 0000000..130ecec
--- /dev/null
+++ b/app/(auth)/reset-password/page.tsx
@@ -0,0 +1,26 @@
+import { Suspense } from "react";
+import { LoginPageShell } from "@/components/auth/login-form";
+import { ResetPasswordForm } from "@/components/auth/reset-password-form";
+import { YaltopiaFooter } from "@/components/layout/YaltopiaFooter";
+
+function ResetPasswordFallback() {
+ return Loading…
;
+}
+
+export default function ResetPasswordPage() {
+ return (
+ <>
+
+ }>
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/app/(auth)/signup/manager/page.tsx b/app/(auth)/signup/manager/page.tsx
new file mode 100644
index 0000000..65037af
--- /dev/null
+++ b/app/(auth)/signup/manager/page.tsx
@@ -0,0 +1,11 @@
+import { SignupForm } from "@/components/auth/signup-form";
+
+export default function ManagerSignupPage() {
+ return (
+
+ );
+}
diff --git a/app/(auth)/signup/master/page.tsx b/app/(auth)/signup/master/page.tsx
new file mode 100644
index 0000000..6491d18
--- /dev/null
+++ b/app/(auth)/signup/master/page.tsx
@@ -0,0 +1,11 @@
+import { SignupForm } from "@/components/auth/signup-form";
+
+export default function MasterSignupPage() {
+ return (
+
+ );
+}
diff --git a/app/(auth)/signup/page.tsx b/app/(auth)/signup/page.tsx
new file mode 100644
index 0000000..1e76709
--- /dev/null
+++ b/app/(auth)/signup/page.tsx
@@ -0,0 +1,5 @@
+import { redirect } from "next/navigation";
+
+export default function SignupPage() {
+ redirect("/signup/manager");
+}
diff --git a/app/(dashboard)/layout.tsx b/app/(dashboard)/layout.tsx
new file mode 100644
index 0000000..4af9998
--- /dev/null
+++ b/app/(dashboard)/layout.tsx
@@ -0,0 +1,9 @@
+import { AppShell } from "@/components/layout/AppShell";
+
+export default function DashboardLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return {children} ;
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/admin/results/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/admin/results/page.tsx
new file mode 100644
index 0000000..b66600e
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/admin/results/page.tsx
@@ -0,0 +1,65 @@
+import Link from "next/link";
+import { createClient } from "@/lib/supabase/server";
+import { GlassCard } from "@/components/ui/glass-card";
+import { TeamBadge } from "@/components/teams/TeamBadge";
+
+export default async function AdminResultsPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string; competitionId: string }>;
+}) {
+ const { leagueId, competitionId } = await params;
+ const supabase = await createClient();
+
+ const { data: pending } = await supabase
+ .from("matches")
+ .select(
+ `*, home:home_team_id(name, logo_path), away:away_team_id(name, logo_path)`
+ )
+ .eq("competition_id", competitionId)
+ .in("result_status", ["pending_approval", "disputed"]);
+
+ return (
+
+
Results admin
+
+ Approve or resolve match results as league manager
+
+
+
+
+ {pending?.map((m) => {
+ const home = m.home as { name: string; logo_path: string | null };
+ const away = m.away as { name: string; logo_path: string | null };
+ return (
+
+
+
+
+ vs
+
+
+
+ {m.result_status}
+
+
+
+ );
+ })}
+ {(!pending || pending.length === 0) && (
+ No pending results
+ )}
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/fixtures/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/fixtures/page.tsx
new file mode 100644
index 0000000..47d77ae
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/fixtures/page.tsx
@@ -0,0 +1,59 @@
+import Link from "next/link";
+import { createClient } from "@/lib/supabase/server";
+import { GlassCard } from "@/components/ui/glass-card";
+import { TeamBadge } from "@/components/teams/TeamBadge";
+
+export default async function FixturesPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string; competitionId: string }>;
+}) {
+ const { leagueId, competitionId } = await params;
+ const supabase = await createClient();
+
+ const { data: matches } = await supabase
+ .from("matches")
+ .select(
+ `*, home:home_team_id(id, name, logo_path), away:away_team_id(id, name, logo_path)`
+ )
+ .eq("competition_id", competitionId)
+ .order("matchday")
+ .order("round");
+
+ return (
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/layout.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/layout.tsx
new file mode 100644
index 0000000..201d7e5
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/layout.tsx
@@ -0,0 +1,75 @@
+import Link from "next/link";
+import { notFound } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import { CompetitionSidebar } from "@/components/layout/Sidebar";
+import { YaltopiaFooter } from "@/components/layout/YaltopiaFooter";
+
+export default async function CompetitionLayout({
+ children,
+ params,
+}: {
+ children: React.ReactNode;
+ params: Promise<{ leagueId: string; competitionId: string }>;
+}) {
+ const { leagueId, competitionId } = await params;
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+
+ const { data: competition } = await supabase
+ .from("competitions")
+ .select("*, leagues(name)")
+ .eq("id", competitionId)
+ .single();
+
+ if (!competition) notFound();
+
+ let showMyTeam = false;
+ if (user) {
+ const { data: compTeams } = await supabase
+ .from("teams")
+ .select("id")
+ .eq("competition_id", competitionId);
+ const ids = compTeams?.map((t) => t.id) ?? [];
+ if (ids.length > 0) {
+ const { count } = await supabase
+ .from("team_members")
+ .select("id", { count: "exact", head: true })
+ .eq("user_id", user.id)
+ .eq("role", "manager")
+ .in("team_id", ids);
+ showMyTeam = (count ?? 0) > 0;
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/matches/[matchId]/match-actions.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/matches/[matchId]/match-actions.tsx
new file mode 100644
index 0000000..27e7cd0
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/matches/[matchId]/match-actions.tsx
@@ -0,0 +1,168 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+
+export function MatchActions({
+ matchId,
+ homeTeamId,
+ awayTeamId,
+ userTeamId,
+ status,
+ resultStatus,
+ isLeagueManager,
+ proposedAt,
+}: {
+ matchId: string;
+ homeTeamId: string;
+ awayTeamId: string;
+ userTeamId: string | null;
+ status: string;
+ resultStatus: string | null;
+ isLeagueManager: boolean;
+ proposedAt: string | null;
+}) {
+ const router = useRouter();
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ async function run(fn: () => Promise) {
+ setLoading(true);
+ setError(null);
+ try {
+ await fn();
+ router.refresh();
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "Error");
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return (
+
+ {error &&
{error}
}
+
+ {userTeamId && status !== "completed" && (
+
+ {proposedAt && (
+
+ Proposed: {new Date(proposedAt).toLocaleString()}
+
+ )}
+
+
+ run(() => api.matches.signSchedule(matchId, userTeamId!))
+ }
+ >
+ Sign schedule
+
+
+ )}
+
+ {userTeamId && status !== "completed" && (
+
+
+
+ )}
+
+ {isLeagueManager && resultStatus === "pending_approval" && (
+
+ run(() => api.matches.approveResult(matchId))}
+ >
+ Approve matching result
+
+
+ )}
+
+ {isLeagueManager && (
+
+
+
+ )}
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/matches/[matchId]/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/matches/[matchId]/page.tsx
new file mode 100644
index 0000000..6899fb0
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/matches/[matchId]/page.tsx
@@ -0,0 +1,124 @@
+import { notFound } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import { MatchActions } from "./match-actions";
+import { GlassCard } from "@/components/ui/glass-card";
+import { TeamBadge } from "@/components/teams/TeamBadge";
+
+export default async function MatchPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string; competitionId: string; matchId: string }>;
+}) {
+ const { leagueId, competitionId, matchId } = await params;
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+
+ const { data: match } = await supabase
+ .from("matches")
+ .select(
+ `*, home:home_team_id(id, name, logo_path), away:away_team_id(id, name, logo_path)`
+ )
+ .eq("id", matchId)
+ .single();
+
+ if (!match) notFound();
+
+ const home = match.home as { id: string; name: string; logo_path: string | null };
+ const away = match.away as { id: string; name: string; logo_path: string | null };
+
+ const { data: submissions } = await supabase
+ .from("match_result_submissions")
+ .select("*, teams(name)")
+ .eq("match_id", matchId);
+
+ const { data: signatures } = await supabase
+ .from("match_signatures")
+ .select("team_id, teams(name)")
+ .eq("match_id", matchId);
+
+ let userTeamId: string | null = null;
+ if (user) {
+ const { data: tm } = await supabase
+ .from("team_members")
+ .select("team_id")
+ .eq("user_id", user.id)
+ .in("team_id", [home.id, away.id])
+ .limit(1)
+ .single();
+ userTeamId = tm?.team_id ?? null;
+ }
+
+ const { data: isLeagueManager } = user
+ ? await supabase
+ .from("competition_league_managers")
+ .select("id")
+ .eq("competition_id", competitionId)
+ .eq("user_id", user.id)
+ .maybeSingle()
+ : { data: null };
+
+ return (
+
+
+
+
+
+
+ {match.status === "completed"
+ ? `${match.home_score} – ${match.away_score}`
+ : "vs"}
+
+
+ {match.status.replace(/_/g, " ")}
+
+ {match.venue && (
+
{match.venue}
+ )}
+
+
+
+
+
+
+
+
+ {signatures?.map((s) => (
+
+ ✓ {(s.teams as { name: string })?.name} signed
+
+ ))}
+ {(!signatures || signatures.length === 0) && (
+ No signatures yet
+ )}
+
+
+
+
+
+ {submissions?.map((s) => (
+
+ {(s.teams as { name: string })?.name}: {s.home_score}–{s.away_score}
+
+ ))}
+ {(!submissions || submissions.length === 0) && (
+ No submissions yet
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/my-team/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/my-team/page.tsx
new file mode 100644
index 0000000..d343da3
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/my-team/page.tsx
@@ -0,0 +1,200 @@
+import { redirect } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import {
+ FormDonut,
+ GoalsTrendChart,
+ TopScorersChart,
+ StatCards,
+} from "@/components/manager/TeamCharts";
+import { GlassCard } from "@/components/ui/glass-card";
+import { TeamBadge } from "@/components/teams/TeamBadge";
+
+export default async function MyTeamPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string; competitionId: string }>;
+}) {
+ const { leagueId, competitionId } = await params;
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) redirect("/login");
+
+ const { data: teamsInComp } = await supabase
+ .from("teams")
+ .select("id")
+ .eq("competition_id", competitionId);
+ const teamIds = teamsInComp?.map((t) => t.id) ?? [];
+
+ const { data: membership } = await supabase
+ .from("team_members")
+ .select("team_id, teams(*)")
+ .eq("user_id", user.id)
+ .eq("role", "manager")
+ .in("team_id", teamIds.length ? teamIds : ["00000000-0000-0000-0000-000000000000"])
+ .limit(1)
+ .maybeSingle();
+
+ if (!membership) {
+ return (
+
+ You are not a team manager in this competition.
+
+ );
+ }
+
+ const team = membership.teams as {
+ id: string;
+ name: string;
+ logo_path: string | null;
+ };
+
+ const { data: results } = await supabase
+ .from("team_match_results")
+ .select("*")
+ .eq("team_id", team.id)
+ .order("matchday", { ascending: true });
+
+ const { data: playerStats } = await supabase
+ .from("player_competition_stats")
+ .select("*")
+ .eq("team_id", team.id)
+ .eq("competition_id", competitionId)
+ .order("goals", { ascending: false });
+
+ const formCounts = { W: 0, D: 0, L: 0 };
+ results?.slice(-10).forEach((r) => {
+ if (r.result in formCounts) formCounts[r.result as keyof typeof formCounts]++;
+ });
+ const formData = Object.entries(formCounts).map(([name, value]) => ({
+ name,
+ value,
+ }));
+
+ const goalsTrend =
+ results?.map((r, i) => ({
+ matchday: r.matchday ?? i + 1,
+ gf: r.goals_for ?? 0,
+ ga: r.goals_against ?? 0,
+ })) ?? [];
+
+ const topScorers =
+ playerStats?.slice(0, 8).map((p) => ({
+ name: p.player_name,
+ goals: p.goals,
+ })) ?? [];
+
+ const topAssists =
+ playerStats
+ ?.slice()
+ .sort((a, b) => b.assists - a.assists)
+ .slice(0, 8)
+ .map((p) => ({
+ name: p.player_name,
+ assists: p.assists,
+ })) ?? [];
+
+ const played = results?.length ?? 0;
+ const won = results?.filter((r) => r.result === "W").length ?? 0;
+ const drawn = results?.filter((r) => r.result === "D").length ?? 0;
+ const lost = results?.filter((r) => r.result === "L").length ?? 0;
+ const gf = results?.reduce((s, r) => s + (r.goals_for ?? 0), 0) ?? 0;
+ const ga = results?.reduce((s, r) => s + (r.goals_against ?? 0), 0) ?? 0;
+
+ return (
+
+
+
+
+
+
+ d.value > 0)} />
+
+
+
+
+
+
+
+
+
+ Player
+ Apps
+ G
+ A
+ G+A
+
+
+
+ {playerStats?.map((p) => (
+
+ {p.player_name}
+ {p.appearances}
+ {p.goals}
+ {p.assists}
+
+ {p.goals + p.assists}
+
+
+ ))}
+
+
+
+
+
+
+ {results
+ ?.slice()
+ .reverse()
+ .slice(0, 5)
+ .map((r) => (
+
+ vs {r.opponent_name}
+
+ {r.goals_for}–{r.goals_against}{" "}
+
+ {r.result}
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/page.tsx
new file mode 100644
index 0000000..9ddd800
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/page.tsx
@@ -0,0 +1,95 @@
+import { notFound } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import { GlassCard } from "@/components/ui/glass-card";
+import { CompetitionDraftPanel } from "@/components/competitions/competition-draft-panel";
+import { StandingsTable } from "@/components/standings/StandingsTable";
+import { TeamBadge } from "@/components/teams/TeamBadge";
+import Link from "next/link";
+
+export default async function CompetitionPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string; competitionId: string }>;
+}) {
+ const { leagueId, competitionId } = await params;
+ const supabase = await createClient();
+
+ const { data: competition } = await supabase
+ .from("competitions")
+ .select("*")
+ .eq("id", competitionId)
+ .single();
+
+ if (!competition) notFound();
+
+ const { data: teams } = await supabase
+ .from("teams")
+ .select("*")
+ .eq("competition_id", competitionId)
+ .order("name");
+
+ const { data: standings } = await supabase
+ .from("competition_standings")
+ .select("*")
+ .eq("competition_id", competitionId);
+
+ const { data: upcoming } = await supabase
+ .from("matches")
+ .select(
+ `*, home:home_team_id(name, logo_path), away:away_team_id(name, logo_path)`
+ )
+ .eq("competition_id", competitionId)
+ .in("status", ["scheduled", "schedule_pending", "schedule_confirmed"])
+ .order("scheduled_at")
+ .limit(5);
+
+ return (
+
+
+
{competition.name}
+
+
+ {competition.status === "draft" && (
+
+ )}
+
+ {competition.tournament_mode === "league" && standings && standings.length > 0 && (
+
+
+
+ )}
+
+
+
+ {upcoming?.map((m) => {
+ const home = m.home as { name: string; logo_path: string | null };
+ const away = m.away as { name: string; logo_path: string | null };
+ return (
+
+
+
+
+ vs
+
+
+
+ {m.status.replace(/_/g, " ")}
+
+
+
+ );
+ })}
+ {(!upcoming || upcoming.length === 0) && (
+ No upcoming fixtures
+ )}
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/playoffs/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/playoffs/page.tsx
new file mode 100644
index 0000000..3eb18d1
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/playoffs/page.tsx
@@ -0,0 +1,17 @@
+import { GlassCard } from "@/components/ui/glass-card";
+
+export default function PlayoffsPage() {
+ return (
+
+
Champions League playoffs
+
+
+ End-of-season qualification playoffs activate when the competition
+ status is set to playoffs {" "}
+ after all league matches are completed. Top teams auto-qualify per
+ league rules; remaining teams play in for the final CL spots.
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/teams/[teamId]/settings/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/teams/[teamId]/settings/page.tsx
new file mode 100644
index 0000000..b230017
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/teams/[teamId]/settings/page.tsx
@@ -0,0 +1,32 @@
+import { notFound } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import { TeamSettingsForm } from "./team-settings-form";
+
+export default async function TeamSettingsPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string; competitionId: string; teamId: string }>;
+}) {
+ const { teamId } = await params;
+ const supabase = await createClient();
+
+ const { data: team } = await supabase
+ .from("teams")
+ .select("*")
+ .eq("id", teamId)
+ .single();
+
+ if (!team) notFound();
+
+ const { data: availability } = await supabase
+ .from("team_availability")
+ .select("*")
+ .eq("team_id", teamId);
+
+ return (
+
+
Team settings — {team.name}
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/teams/[teamId]/settings/team-settings-form.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/teams/[teamId]/settings/team-settings-form.tsx
new file mode 100644
index 0000000..7445d07
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/teams/[teamId]/settings/team-settings-form.tsx
@@ -0,0 +1,110 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { api } from "@/lib/api/client";
+import { createClient } from "@/lib/supabase/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { DAY_NAMES } from "@/lib/utils";
+
+export function TeamSettingsForm({
+ team,
+ availability,
+}: {
+ team: { id: string; name: string; home_stadium_name: string | null; logo_path: string | null; competition_id: string };
+ availability: { day_of_week: number; start_time: string | null; end_time: string | null }[];
+}) {
+ const router = useRouter();
+ const [stadium, setStadium] = useState(team.home_stadium_name ?? "");
+ const [days, setDays] = useState(
+ [...new Set(availability.map((a) => a.day_of_week))]
+ );
+ const [loading, setLoading] = useState(false);
+
+ async function saveStadium() {
+ setLoading(true);
+ await api.teams.update(team.id, { home_stadium_name: stadium });
+ setLoading(false);
+ router.refresh();
+ }
+
+ async function uploadLogo(e: React.ChangeEvent) {
+ const file = e.target.files?.[0];
+ if (!file) return;
+ const supabase = createClient();
+ const ext = file.name.split(".").pop();
+ const path = `${team.competition_id}/${team.id}/logo.${ext}`;
+ const { error } = await supabase.storage
+ .from("team-logos")
+ .upload(path, file, { upsert: true });
+ if (error) {
+ alert(error.message);
+ return;
+ }
+ await api.teams.update(team.id, { logo_path: path });
+ router.refresh();
+ }
+
+ async function saveAvailability() {
+ setLoading(true);
+ await api.teams.setAvailability(
+ team.id,
+ days.map((d) => ({ day_of_week: d }))
+ );
+ setLoading(false);
+ router.refresh();
+ }
+
+ function toggleDay(d: number) {
+ setDays((prev) =>
+ prev.includes(d) ? prev.filter((x) => x !== d) : [...prev, d]
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+ setStadium(e.target.value)}
+ placeholder="Arena name"
+ className="flex-1"
+ />
+
+ Save
+
+
+
+
+
+
+ {DAY_NAMES.map((name, i) => (
+ toggleDay(i)}
+ className={`rounded-lg px-3 py-2 text-sm ${
+ days.includes(i)
+ ? "bg-cyan-500/20 text-cyan-400"
+ : "bg-white/5 text-[var(--color-muted)]"
+ }`}
+ >
+ {name}
+
+ ))}
+
+
+ Save availability
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/transfers/page.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/transfers/page.tsx
new file mode 100644
index 0000000..8bae7a0
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/transfers/page.tsx
@@ -0,0 +1,55 @@
+import { createClient } from "@/lib/supabase/server";
+import { TransfersPanel } from "./transfers-panel";
+import { GlassCard } from "@/components/ui/glass-card";
+
+export default async function TransfersPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string; competitionId: string }>;
+}) {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+
+ const { data: transfers } = await supabase
+ .from("transfers")
+ .select(
+ `*, player:players(display_name), from_team:from_team_id(name), to_team:to_team_id(name)`
+ )
+ .eq("competition_id", competitionId)
+ .order("created_at", { ascending: false })
+ .limit(20);
+
+ const { data: teams } = await supabase
+ .from("teams")
+ .select("id, name")
+ .eq("competition_id", competitionId);
+
+ const { data: players } = await supabase
+ .from("players")
+ .select("id, display_name")
+ .eq("status", "active");
+
+ return (
+
+
Transfers
+
+
+
+ {transfers?.map((t) => (
+
+
+ {(t.player as { display_name: string })?.display_name}
+ {" "}
+ {(t.from_team as { name: string })?.name} →{" "}
+ {(t.to_team as { name: string })?.name}
+
+ ))}
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/transfers/transfers-panel.tsx b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/transfers/transfers-panel.tsx
new file mode 100644
index 0000000..a58ba05
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/transfers/transfers-panel.tsx
@@ -0,0 +1,138 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Label } from "@/components/ui/label";
+
+export function TransfersPanel({
+ competitionId,
+ teams,
+ players,
+}: {
+ competitionId: string;
+ teams: { id: string; name: string }[];
+ players: { id: string; display_name: string }[];
+}) {
+ const router = useRouter();
+ const [loading, setLoading] = useState(false);
+
+ return (
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/page.tsx b/app/(dashboard)/leagues/[leagueId]/page.tsx
new file mode 100644
index 0000000..7e07ce6
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/page.tsx
@@ -0,0 +1,89 @@
+import Link from "next/link";
+import { notFound } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import { createCompetition } from "@/actions/leagues";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+
+export default async function LeaguePage({
+ params,
+}: {
+ params: Promise<{ leagueId: string }>;
+}) {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+
+ const { data: league } = await supabase
+ .from("leagues")
+ .select("*")
+ .eq("id", leagueId)
+ .single();
+
+ if (!league) notFound();
+
+ const { data: competitions } = await supabase
+ .from("competitions")
+ .select("*")
+ .eq("league_id", leagueId)
+ .order("created_at", { ascending: false });
+
+ return (
+
+
+
+
{league.name}
+
{league.description}
+
+
+ Edit rules
+
+
+
+
+
+
+
+
+ {competitions?.map((c) => (
+
+
+
+
+
{c.name}
+
+ {c.tournament_mode} · {c.status}
+
+
+
+ {c.status}
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/rules/page.tsx b/app/(dashboard)/leagues/[leagueId]/rules/page.tsx
new file mode 100644
index 0000000..54e0fe7
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/rules/page.tsx
@@ -0,0 +1,45 @@
+import { notFound } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import { parseLeagueRules, defaultLeagueRules } from "@/lib/rules/schema";
+import { RulesForm } from "./rules-form";
+
+export default async function RulesPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string }>;
+}) {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+
+ const { data: league } = await supabase
+ .from("leagues")
+ .select("name")
+ .eq("id", leagueId)
+ .single();
+
+ if (!league) notFound();
+
+ const { data: latest } = await supabase
+ .from("league_rules")
+ .select("rules, version")
+ .eq("league_id", leagueId)
+ .order("version", { ascending: false })
+ .limit(1)
+ .single();
+
+ const rules = latest?.rules
+ ? parseLeagueRules(latest.rules)
+ : defaultLeagueRules;
+
+ return (
+
+
+
League rules
+
+ {league.name} · version {latest?.version ?? 0}
+
+
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/[leagueId]/rules/rules-form.tsx b/app/(dashboard)/leagues/[leagueId]/rules/rules-form.tsx
new file mode 100644
index 0000000..4e6f23b
--- /dev/null
+++ b/app/(dashboard)/leagues/[leagueId]/rules/rules-form.tsx
@@ -0,0 +1,94 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import type { LeagueRules } from "@/lib/rules/schema";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { api } from "@/lib/api/client";
+
+export function RulesForm({
+ leagueId,
+ initialRules,
+}: {
+ leagueId: string;
+ initialRules: LeagueRules;
+}) {
+ const router = useRouter();
+ const [rules, setRules] = useState(initialRules);
+ const [loading, setLoading] = useState(false);
+
+ async function handleSave() {
+ setLoading(true);
+ try {
+ await api.leagues.saveRules(leagueId, rules);
+ router.refresh();
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return (
+
+
+
+ Points for win
+
+ setRules({ ...rules, points_win: Number(e.target.value) })
+ }
+ className="mt-1"
+ />
+
+
+ Points for draw
+
+ setRules({ ...rules, points_draw: Number(e.target.value) })
+ }
+ className="mt-1"
+ />
+
+
+ Round robin
+
+ setRules({
+ ...rules,
+ round_robin_format: e.target.value as "single" | "double",
+ })
+ }
+ className="mt-1 flex h-10 w-full rounded-lg border border-white/15 bg-white/5 px-3 text-sm"
+ >
+ Single
+ Double
+
+
+
+ Auto-qualify (CL)
+
+ setRules({
+ ...rules,
+ auto_qualify_count: Number(e.target.value),
+ })
+ }
+ className="mt-1"
+ />
+
+
+
+ Save new rules version
+
+
+ );
+}
diff --git a/app/(dashboard)/leagues/page.tsx b/app/(dashboard)/leagues/page.tsx
new file mode 100644
index 0000000..216292b
--- /dev/null
+++ b/app/(dashboard)/leagues/page.tsx
@@ -0,0 +1,71 @@
+import Link from "next/link";
+import { createClient } from "@/lib/supabase/server";
+import { createLeague } from "@/actions/leagues";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { Trophy, Plus } from "lucide-react";
+
+export default async function LeaguesPage() {
+ const supabase = await createClient();
+ const { data: leagues } = await supabase
+ .from("leagues")
+ .select("*")
+ .order("created_at", { ascending: false });
+
+ return (
+
+
+
+
Leagues
+
+ Create and manage tournament leagues
+
+
+
+
+
+
+
+
+
+ {leagues?.map((league) => (
+
+
+
+
+
+
+
+
{league.name}
+
+ {league.description || "No description"}
+
+
+
+
+
+ ))}
+ {(!leagues || leagues.length === 0) && (
+
+ No leagues yet. Create your first league above.
+
+ )}
+
+
+ );
+}
diff --git a/app/(dashboard)/players/page.tsx b/app/(dashboard)/players/page.tsx
new file mode 100644
index 0000000..5c818d6
--- /dev/null
+++ b/app/(dashboard)/players/page.tsx
@@ -0,0 +1,82 @@
+import { createClient } from "@/lib/supabase/server";
+import { createPlayer, togglePlayerStatus } from "@/actions/players";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+
+export default async function PlayersPage() {
+ const supabase = await createClient();
+ const { data: players } = await supabase
+ .from("players")
+ .select("*")
+ .order("display_name");
+
+ return (
+
+
+
Player registry
+
+ Load players before roster adds or transfers
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+ External ID
+ Status
+ Actions
+
+
+
+ {players?.map((p) => (
+
+ {p.display_name}
+
+ {p.external_id || "—"}
+
+
+
+ {p.status}
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/app/(manager)/layout.tsx b/app/(manager)/layout.tsx
new file mode 100644
index 0000000..f2669bf
--- /dev/null
+++ b/app/(manager)/layout.tsx
@@ -0,0 +1,21 @@
+import { redirect } from "next/navigation";
+import { requirePortalRole } from "@/lib/auth/profile";
+import { ManagerShell } from "@/components/layout/ManagerShell";
+
+export default async function ManagerLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ const gate = await requirePortalRole("manager");
+ if (!gate.ok) {
+ redirect(gate.reason === "auth" ? "/login/manager" : "/login/master");
+ }
+
+ const user = {
+ name: gate.profile?.display_name ?? gate.user.email?.split("@")[0] ?? "Manager",
+ email: gate.user.email ?? "",
+ };
+
+ return {children} ;
+}
diff --git a/app/(manager)/manager/calendar/page.tsx b/app/(manager)/manager/calendar/page.tsx
new file mode 100644
index 0000000..b7da6ae
--- /dev/null
+++ b/app/(manager)/manager/calendar/page.tsx
@@ -0,0 +1,11 @@
+import { MatchCalendar } from "@/components/calendar/match-calendar";
+
+export default function ManagerCalendarPage() {
+ return (
+
+ );
+}
diff --git a/app/(manager)/manager/cups/page.tsx b/app/(manager)/manager/cups/page.tsx
new file mode 100644
index 0000000..4d315a6
--- /dev/null
+++ b/app/(manager)/manager/cups/page.tsx
@@ -0,0 +1,11 @@
+import { ManagerCompetitionsTable } from "@/components/manager/manager-competitions-table";
+
+export default function ManagerCupsPage() {
+ return (
+
+ );
+}
diff --git a/app/(manager)/manager/faq/page.tsx b/app/(manager)/manager/faq/page.tsx
new file mode 100644
index 0000000..4844bd8
--- /dev/null
+++ b/app/(manager)/manager/faq/page.tsx
@@ -0,0 +1,21 @@
+import { PageHeader } from "@/components/dashboard/page-header";
+import { GlassCard } from "@/components/ui/glass-card";
+import { MANAGER_FAQ } from "@/lib/content/faq";
+
+export default function ManagerFaqPage() {
+ return (
+
+
+
+ {MANAGER_FAQ.map((item) => (
+
+ {item.a}
+
+ ))}
+
+
+ );
+}
diff --git a/app/(manager)/manager/issues/page.tsx b/app/(manager)/manager/issues/page.tsx
new file mode 100644
index 0000000..c683371
--- /dev/null
+++ b/app/(manager)/manager/issues/page.tsx
@@ -0,0 +1,26 @@
+import { createClient } from "@/lib/supabase/server";
+import { getCurrentProfile } from "@/lib/auth/profile";
+import { IssuesPanel } from "@/components/issues/issues-panel";
+
+export default async function ManagerIssuesPage() {
+ const supabase = await createClient();
+ const ctx = await getCurrentProfile();
+
+ const { data: memberships } = await supabase
+ .from("team_members")
+ .select("teams(competitions(league_id, leagues(id, name)))")
+ .eq("user_id", ctx!.user.id);
+
+ const leagueMap = new Map();
+ memberships?.forEach((m) => {
+ const team = m.teams as {
+ competitions: { leagues: { id: string; name: string } | null } | null;
+ } | null;
+ const league = team?.competitions?.leagues;
+ if (league) leagueMap.set(league.id, league.name);
+ });
+
+ const leagues = [...leagueMap.entries()].map(([id, name]) => ({ id, name }));
+
+ return ;
+}
diff --git a/app/(manager)/manager/leagues/page.tsx b/app/(manager)/manager/leagues/page.tsx
new file mode 100644
index 0000000..d7e2b9a
--- /dev/null
+++ b/app/(manager)/manager/leagues/page.tsx
@@ -0,0 +1,11 @@
+import { ManagerCompetitionsTable } from "@/components/manager/manager-competitions-table";
+
+export default function ManagerLeaguesPage() {
+ return (
+
+ );
+}
diff --git a/app/(manager)/manager/page.tsx b/app/(manager)/manager/page.tsx
new file mode 100644
index 0000000..dfa8bbc
--- /dev/null
+++ b/app/(manager)/manager/page.tsx
@@ -0,0 +1,5 @@
+import { ManagerDashboardClient } from "@/components/manager/manager-dashboard-client";
+
+export default function ManagerDashboardPage() {
+ return ;
+}
diff --git a/app/(manager)/manager/rules/page.tsx b/app/(manager)/manager/rules/page.tsx
new file mode 100644
index 0000000..e7d9043
--- /dev/null
+++ b/app/(manager)/manager/rules/page.tsx
@@ -0,0 +1,96 @@
+import { createClient } from "@/lib/supabase/server";
+import { getCurrentProfile } from "@/lib/auth/profile";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { GlassCard } from "@/components/ui/glass-card";
+import Link from "next/link";
+import { parseLeagueRules, defaultLeagueRules } from "@/lib/rules/schema";
+
+export default async function ManagerRulesPage() {
+ const supabase = await createClient();
+ const ctx = await getCurrentProfile();
+
+ const { data: memberships } = await supabase
+ .from("team_members")
+ .select("teams(competition_id, competitions(league_id, name, leagues(name)))")
+ .eq("user_id", ctx!.user.id)
+ .eq("role", "manager");
+
+ const leagueIds = new Set();
+ const leagueNames = new Map();
+
+ memberships?.forEach((m) => {
+ const team = m.teams as {
+ competitions: { league_id: string; leagues: { name: string } | null } | null;
+ } | null;
+ const leagueId = team?.competitions?.league_id;
+ const name = team?.competitions?.leagues?.name;
+ if (leagueId) {
+ leagueIds.add(leagueId);
+ if (name) leagueNames.set(leagueId, name);
+ }
+ });
+
+ const rulesBlocks = await Promise.all(
+ [...leagueIds].map(async (leagueId) => {
+ const { data: latest } = await supabase
+ .from("league_rules")
+ .select("rules, version")
+ .eq("league_id", leagueId)
+ .order("version", { ascending: false })
+ .limit(1)
+ .single();
+ const rules = latest?.rules
+ ? parseLeagueRules(latest.rules)
+ : defaultLeagueRules;
+ return { leagueId, name: leagueNames.get(leagueId) ?? "League", rules, version: latest?.version ?? 0 };
+ })
+ );
+
+ return (
+
+
+ {rulesBlocks.length === 0 ? (
+
+
+ No league rules available yet. You need to be assigned as a team manager.
+
+
+ ) : (
+ rulesBlocks.map((block) => (
+
+
+
+
Win points
+ {block.rules.points_win}
+
+
+
Draw points
+ {block.rules.points_draw}
+
+
+
Format
+ {block.rules.round_robin_format}
+
+
+
Auto-qualify (CL)
+ {block.rules.auto_qualify_count}
+
+
+
+ View full rules page
+
+
+ ))
+ )}
+
+ );
+}
diff --git a/app/(master)/layout.tsx b/app/(master)/layout.tsx
new file mode 100644
index 0000000..3540518
--- /dev/null
+++ b/app/(master)/layout.tsx
@@ -0,0 +1,21 @@
+import { redirect } from "next/navigation";
+import { requirePortalRole } from "@/lib/auth/profile";
+import { MasterShell } from "@/components/layout/MasterShell";
+
+export default async function MasterLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ const gate = await requirePortalRole("league_master");
+ if (!gate.ok) {
+ redirect(gate.reason === "auth" ? "/login/master" : "/login/manager");
+ }
+
+ const user = {
+ name: gate.profile?.display_name ?? gate.user.email?.split("@")[0] ?? "Master",
+ email: gate.user.email ?? "",
+ };
+
+ return {children} ;
+}
diff --git a/app/(master)/master/calendar/page.tsx b/app/(master)/master/calendar/page.tsx
new file mode 100644
index 0000000..b2b007f
--- /dev/null
+++ b/app/(master)/master/calendar/page.tsx
@@ -0,0 +1,11 @@
+import { MatchCalendar } from "@/components/calendar/match-calendar";
+
+export default function MasterCalendarPage() {
+ return (
+
+ );
+}
diff --git a/app/(master)/master/issues/page.tsx b/app/(master)/master/issues/page.tsx
new file mode 100644
index 0000000..33a3ec7
--- /dev/null
+++ b/app/(master)/master/issues/page.tsx
@@ -0,0 +1,11 @@
+import { createClient } from "@/lib/supabase/server";
+import { IssuesPanel } from "@/components/issues/issues-panel";
+
+export default async function MasterIssuesPage() {
+ const supabase = await createClient();
+ const { data: leagues } = await supabase.from("leagues").select("id, name");
+
+ return (
+
+ );
+}
diff --git a/app/(master)/master/leagues/[leagueId]/competitions/new/page.tsx b/app/(master)/master/leagues/[leagueId]/competitions/new/page.tsx
new file mode 100644
index 0000000..cc51193
--- /dev/null
+++ b/app/(master)/master/leagues/[leagueId]/competitions/new/page.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter, useParams } from "next/navigation";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { PageHeader } from "@/components/dashboard/page-header";
+
+export default function NewCompetitionPage() {
+ const router = useRouter();
+ const params = useParams();
+ const leagueId = params.leagueId as string;
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ return (
+
+ );
+}
diff --git a/app/(master)/master/leagues/[leagueId]/page.tsx b/app/(master)/master/leagues/[leagueId]/page.tsx
new file mode 100644
index 0000000..b3e0501
--- /dev/null
+++ b/app/(master)/master/leagues/[leagueId]/page.tsx
@@ -0,0 +1,65 @@
+import Link from "next/link";
+import { notFound } from "next/navigation";
+import { createClient } from "@/lib/supabase/server";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+
+export default async function MasterLeagueDetailPage({
+ params,
+}: {
+ params: Promise<{ leagueId: string }>;
+}) {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+
+ const { data: league } = await supabase
+ .from("leagues")
+ .select("*, competitions(*)")
+ .eq("id", leagueId)
+ .single();
+
+ if (!league) notFound();
+
+ return (
+
+
+ Edit rules
+
+ }
+ />
+
+
+
+ {league.competitions?.map(
+ (c: { id: string; name: string; status: string; tournament_mode: string }) => (
+
+
+ {c.name}
+
+ {c.tournament_mode} · {c.status}
+
+
+
+ )
+ )}
+ {(!league.competitions || league.competitions.length === 0) && (
+ No competitions yet
+ )}
+
+
+
+ Add competition
+
+
+
+
+ );
+}
diff --git a/app/(master)/master/leagues/page.tsx b/app/(master)/master/leagues/page.tsx
new file mode 100644
index 0000000..12681e7
--- /dev/null
+++ b/app/(master)/master/leagues/page.tsx
@@ -0,0 +1,18 @@
+import { createClient } from "@/lib/supabase/server";
+import { getCurrentProfile } from "@/lib/auth/profile";
+import { listLeaguesForMaster } from "@/lib/services/leagues";
+import { MasterLeaguesClient } from "@/components/master/master-leagues-client";
+
+export default async function MasterLeaguesPage() {
+ const supabase = await createClient();
+ const ctx = await getCurrentProfile();
+ const isGlobal = ctx?.profile?.portal_role === "league_master";
+
+ const leagues = await listLeaguesForMaster(
+ supabase,
+ ctx!.user.id,
+ !!isGlobal
+ );
+
+ return ;
+}
diff --git a/app/(master)/master/page.tsx b/app/(master)/master/page.tsx
new file mode 100644
index 0000000..26373bc
--- /dev/null
+++ b/app/(master)/master/page.tsx
@@ -0,0 +1,103 @@
+import { createClient } from "@/lib/supabase/server";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { StatCard } from "@/components/dashboard/stat-card";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Trophy, Users, Inbox, Shield } from "lucide-react";
+import Link from "next/link";
+import { MasterAssignPanel } from "@/components/master/master-assign-panel";
+
+export default async function MasterDashboardPage() {
+ const supabase = await createClient();
+
+ const [{ count: leagues }, { count: players }, { data: openIssues }] =
+ await Promise.all([
+ supabase.from("leagues").select("*", { count: "exact", head: true }),
+ supabase.from("players").select("*", { count: "exact", head: true }),
+ supabase
+ .from("support_issues")
+ .select("id, subject, status, created_at, leagues(name)")
+ .eq("status", "open")
+ .order("created_at", { ascending: false })
+ .limit(5),
+ ]);
+
+ return (
+
+
+ Manage leagues
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ View all issues
+
+
+
+
+ );
+}
diff --git a/app/(master)/master/players/page.tsx b/app/(master)/master/players/page.tsx
new file mode 100644
index 0000000..e137b4b
--- /dev/null
+++ b/app/(master)/master/players/page.tsx
@@ -0,0 +1,21 @@
+import { createClient } from "@/lib/supabase/server";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { PlayersRegistry } from "@/components/players/players-registry";
+
+export default async function MasterPlayersPage() {
+ const supabase = await createClient();
+ const { data: players } = await supabase
+ .from("players")
+ .select("*")
+ .order("display_name");
+
+ return (
+
+ );
+}
diff --git a/app/api/auth/signup/route.ts b/app/api/auth/signup/route.ts
new file mode 100644
index 0000000..22c5a0a
--- /dev/null
+++ b/app/api/auth/signup/route.ts
@@ -0,0 +1,126 @@
+import { NextResponse } from "next/server";
+import { createAdminClient, hasAdminClient } from "@/lib/supabase/admin";
+import { formatSignupError } from "@/lib/supabase/auth-errors";
+import type { PortalRole } from "@/lib/auth/roles";
+
+type Body = {
+ email?: string;
+ password?: string;
+ displayName?: string;
+ portalRole?: PortalRole;
+};
+
+function parsePortalRole(value: unknown): PortalRole {
+ return value === "league_master" ? "league_master" : "manager";
+}
+
+export async function POST(request: Request) {
+ if (!hasAdminClient()) {
+ return NextResponse.json(
+ {
+ success: false,
+ error:
+ "Server signup is not configured. Add SUPABASE_SERVICE_ROLE_KEY to .env.local or use client signup.",
+ useClient: true,
+ },
+ { status: 503 }
+ );
+ }
+
+ let body: Body;
+ try {
+ body = await request.json();
+ } catch {
+ return NextResponse.json(
+ { success: false, error: "Invalid JSON body" },
+ { status: 400 }
+ );
+ }
+
+ const email = body.email?.trim().toLowerCase();
+ const password = body.password;
+ const displayName = body.displayName?.trim() || email?.split("@")[0] || "User";
+ const portalRole = parsePortalRole(body.portalRole);
+
+ if (!email || !password) {
+ return NextResponse.json(
+ { success: false, error: "Email and password are required" },
+ { status: 400 }
+ );
+ }
+ if (password.length < 6) {
+ return NextResponse.json(
+ { success: false, error: "Password must be at least 6 characters" },
+ { status: 400 }
+ );
+ }
+
+ const autoConfirm =
+ process.env.SUPABASE_AUTO_CONFIRM_EMAIL === "true" ||
+ process.env.NODE_ENV === "development";
+
+ try {
+ const admin = createAdminClient();
+
+ const { data: created, error: createError } =
+ await admin.auth.admin.createUser({
+ email,
+ password,
+ email_confirm: autoConfirm,
+ user_metadata: {
+ display_name: displayName,
+ portal_role: portalRole,
+ },
+ });
+
+ if (createError) {
+ const message = formatSignupError(createError.message);
+ const status = createError.status === 422 ? 422 : 500;
+ return NextResponse.json({ success: false, error: message }, { status });
+ }
+
+ const userId = created.user?.id;
+ if (!userId) {
+ return NextResponse.json(
+ { success: false, error: "User was not created" },
+ { status: 500 }
+ );
+ }
+
+ const { error: profileError } = await admin.from("profiles").upsert(
+ {
+ id: userId,
+ display_name: displayName,
+ portal_role: portalRole,
+ },
+ { onConflict: "id" }
+ );
+
+ if (profileError) {
+ return NextResponse.json(
+ {
+ success: false,
+ error: formatSignupError(
+ profileError.message.includes("portal_role")
+ ? "Database error saving new user"
+ : profileError.message
+ ),
+ },
+ { status: 500 }
+ );
+ }
+
+ return NextResponse.json({
+ success: true,
+ userId,
+ needsEmailConfirmation: !autoConfirm,
+ portalRole,
+ });
+ } catch (e) {
+ const message = e instanceof Error ? e.message : "Signup failed";
+ return NextResponse.json(
+ { success: false, error: formatSignupError(message) },
+ { status: 500 }
+ );
+ }
+}
diff --git a/app/api/competitions/[competitionId]/activate/route.ts b/app/api/competitions/[competitionId]/activate/route.ts
new file mode 100644
index 0000000..791d2ff
--- /dev/null
+++ b/app/api/competitions/[competitionId]/activate/route.ts
@@ -0,0 +1,19 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function POST(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ await leagues.activateCompetition(supabase, competitionId);
+ return apiSuccess({ activated: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/dashboard/route.ts b/app/api/competitions/[competitionId]/dashboard/route.ts
new file mode 100644
index 0000000..eecdc69
--- /dev/null
+++ b/app/api/competitions/[competitionId]/dashboard/route.ts
@@ -0,0 +1,32 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { ApiError, apiError, apiSuccess } from "@/lib/api/errors";
+import * as teams from "@/lib/services/teams";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const membership = await teams.getManagerTeam(
+ supabase,
+ user.id,
+ competitionId
+ );
+ if (!membership) {
+ throw new ApiError(404, "You are not a manager in this competition");
+ }
+ const teamId = membership.team_id;
+ const dashboard = await teams.getTeamDashboard(
+ supabase,
+ teamId,
+ competitionId
+ );
+ return apiSuccess({ team: membership.teams, ...dashboard });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/fixtures/route.ts b/app/api/competitions/[competitionId]/fixtures/route.ts
new file mode 100644
index 0000000..1d736f4
--- /dev/null
+++ b/app/api/competitions/[competitionId]/fixtures/route.ts
@@ -0,0 +1,24 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function POST(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const comp = await leagues.getCompetition(supabase, competitionId);
+ const count = await leagues.generateFixtures(
+ supabase,
+ competitionId,
+ comp.tournament_mode as "league" | "cup"
+ );
+ return apiSuccess({ matchesCreated: count });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/matches/route.ts b/app/api/competitions/[competitionId]/matches/route.ts
new file mode 100644
index 0000000..995fca7
--- /dev/null
+++ b/app/api/competitions/[competitionId]/matches/route.ts
@@ -0,0 +1,19 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as matches from "@/lib/services/matches";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await matches.listMatches(supabase, competitionId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/pending-results/route.ts b/app/api/competitions/[competitionId]/pending-results/route.ts
new file mode 100644
index 0000000..7d05188
--- /dev/null
+++ b/app/api/competitions/[competitionId]/pending-results/route.ts
@@ -0,0 +1,19 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as matchService from "@/lib/services/matches";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await matchService.listPendingResults(supabase, competitionId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/roster/route.ts b/app/api/competitions/[competitionId]/roster/route.ts
new file mode 100644
index 0000000..42b15fa
--- /dev/null
+++ b/app/api/competitions/[competitionId]/roster/route.ts
@@ -0,0 +1,24 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as players from "@/lib/services/players";
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{ teamId: string; playerId: string }>(request);
+ await players.addToRoster(supabase, user.id, {
+ teamId: body.teamId,
+ competitionId,
+ playerId: body.playerId,
+ });
+ return apiSuccess({ added: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/route.ts b/app/api/competitions/[competitionId]/route.ts
new file mode 100644
index 0000000..0a06a61
--- /dev/null
+++ b/app/api/competitions/[competitionId]/route.ts
@@ -0,0 +1,19 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await leagues.getCompetition(supabase, competitionId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/standings/route.ts b/app/api/competitions/[competitionId]/standings/route.ts
new file mode 100644
index 0000000..2c2507c
--- /dev/null
+++ b/app/api/competitions/[competitionId]/standings/route.ts
@@ -0,0 +1,19 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await leagues.getStandings(supabase, competitionId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/teams/route.ts b/app/api/competitions/[competitionId]/teams/route.ts
new file mode 100644
index 0000000..368d6a5
--- /dev/null
+++ b/app/api/competitions/[competitionId]/teams/route.ts
@@ -0,0 +1,39 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as teams from "@/lib/services/teams";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await teams.listTeams(supabase, competitionId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const body = await parseJson<{
+ name: string;
+ nickname?: string;
+ icon?: string;
+ }>(request);
+ const data = await teams.createTeam(supabase, competitionId, body);
+ return apiSuccess(data, 201);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/competitions/[competitionId]/transfers/route.ts b/app/api/competitions/[competitionId]/transfers/route.ts
new file mode 100644
index 0000000..efaabaf
--- /dev/null
+++ b/app/api/competitions/[competitionId]/transfers/route.ts
@@ -0,0 +1,42 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as players from "@/lib/services/players";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await players.listTransfers(supabase, competitionId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ competitionId: string }> }
+) {
+ try {
+ const { competitionId } = await params;
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{
+ playerId: string;
+ fromTeamId: string;
+ toTeamId: string;
+ }>(request);
+ await players.registerTransfer(supabase, user.id, {
+ competitionId,
+ ...body,
+ });
+ return apiSuccess({ transferred: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/health/route.ts b/app/api/health/route.ts
new file mode 100644
index 0000000..3123155
--- /dev/null
+++ b/app/api/health/route.ts
@@ -0,0 +1,31 @@
+import { createClient } from "@/lib/supabase/server";
+import { getSupabaseEnv } from "@/lib/supabase/env";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+
+export async function GET() {
+ try {
+ let urlOk = false;
+ try {
+ const { url } = getSupabaseEnv();
+ urlOk = url.includes(".supabase.co");
+ } catch (e) {
+ return apiSuccess({
+ status: "misconfigured",
+ supabase: false,
+ message: e instanceof Error ? e.message : "Invalid env",
+ });
+ }
+
+ const supabase = await createClient();
+ const { error } = await supabase.from("leagues").select("id").limit(1);
+
+ return apiSuccess({
+ status: error ? "degraded" : "ok",
+ supabase: !error,
+ dbError: error?.message,
+ urlOk,
+ });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/issues/route.ts b/app/api/issues/route.ts
new file mode 100644
index 0000000..b6011fa
--- /dev/null
+++ b/app/api/issues/route.ts
@@ -0,0 +1,43 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as issues from "@/lib/services/issues";
+
+export async function GET(request: Request) {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const { searchParams } = new URL(request.url);
+ const asMaster = searchParams.get("as") === "master";
+ const data = await issues.listIssuesForUser(
+ supabase,
+ user.id,
+ asMaster
+ );
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function POST(request: Request) {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{
+ leagueId: string;
+ competitionId?: string;
+ subject: string;
+ body: string;
+ }>(request);
+ const data = await issues.createIssue(supabase, user.id, {
+ leagueId: body.leagueId,
+ competitionId: body.competitionId,
+ subject: body.subject,
+ body: body.body,
+ });
+ return apiSuccess(data, 201);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/leagues/[leagueId]/competitions/route.ts b/app/api/leagues/[leagueId]/competitions/route.ts
new file mode 100644
index 0000000..006b5ca
--- /dev/null
+++ b/app/api/leagues/[leagueId]/competitions/route.ts
@@ -0,0 +1,24 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ leagueId: string }> }
+) {
+ try {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{
+ name: string;
+ tournament_mode: "league" | "cup";
+ timezone?: string;
+ }>(request);
+ const data = await leagues.createCompetition(supabase, user.id, leagueId, body);
+ return apiSuccess(data, 201);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/leagues/[leagueId]/masters/route.ts b/app/api/leagues/[leagueId]/masters/route.ts
new file mode 100644
index 0000000..46d2a1b
--- /dev/null
+++ b/app/api/leagues/[leagueId]/masters/route.ts
@@ -0,0 +1,44 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { ApiError, apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as masters from "@/lib/services/masters";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ leagueId: string }> }
+) {
+ try {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await masters.listLeagueMasters(supabase, leagueId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ leagueId: string }> }
+) {
+ try {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{ email: string }>(request);
+ const targetId = await masters.getUserIdByEmail(supabase, body.email);
+ if (!targetId) {
+ throw new ApiError(404, "No user found with that email");
+ }
+ await masters.assignLeagueMaster(
+ supabase,
+ leagueId,
+ targetId,
+ user.id
+ );
+ return apiSuccess({ assigned: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/leagues/[leagueId]/route.ts b/app/api/leagues/[leagueId]/route.ts
new file mode 100644
index 0000000..f7da814
--- /dev/null
+++ b/app/api/leagues/[leagueId]/route.ts
@@ -0,0 +1,34 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ leagueId: string }> }
+) {
+ try {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await leagues.getLeague(supabase, leagueId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function DELETE(
+ _request: Request,
+ { params }: { params: Promise<{ leagueId: string }> }
+) {
+ try {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ await leagues.deleteLeague(supabase, leagueId);
+ return apiSuccess({ deleted: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/leagues/[leagueId]/rules/route.ts b/app/api/leagues/[leagueId]/rules/route.ts
new file mode 100644
index 0000000..fcd6d10
--- /dev/null
+++ b/app/api/leagues/[leagueId]/rules/route.ts
@@ -0,0 +1,20 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ leagueId: string }> }
+) {
+ try {
+ const { leagueId } = await params;
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{ rules: object }>(request);
+ await leagues.saveLeagueRules(supabase, user.id, leagueId, body.rules);
+ return apiSuccess({ saved: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/leagues/route.ts b/app/api/leagues/route.ts
new file mode 100644
index 0000000..f65aeaf
--- /dev/null
+++ b/app/api/leagues/route.ts
@@ -0,0 +1,30 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as leagues from "@/lib/services/leagues";
+
+export async function GET() {
+ try {
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await leagues.listLeagues(supabase);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function POST(request: Request) {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{ name: string; description?: string }>(request);
+ if (!body.name?.trim()) {
+ return apiError(new Error("name is required"));
+ }
+ const data = await leagues.createLeague(supabase, user.id, body);
+ return apiSuccess(data, 201);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/manager/calendar/route.ts b/app/api/manager/calendar/route.ts
new file mode 100644
index 0000000..b56a332
--- /dev/null
+++ b/app/api/manager/calendar/route.ts
@@ -0,0 +1,21 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import { getManagerCalendarMatches } from "@/lib/services/calendar";
+
+export async function GET(request: Request) {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const { searchParams } = new URL(request.url);
+ const from = searchParams.get("from");
+ const to = searchParams.get("to");
+ if (!from || !to) {
+ return apiError(new Error("from and to query params required (ISO dates)"));
+ }
+ const data = await getManagerCalendarMatches(supabase, user.id, from, to);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/manager/competitions/route.ts b/app/api/manager/competitions/route.ts
new file mode 100644
index 0000000..afa54a0
--- /dev/null
+++ b/app/api/manager/competitions/route.ts
@@ -0,0 +1,23 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as manager from "@/lib/services/manager";
+
+export async function GET(request: Request) {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const mode = new URL(request.url).searchParams.get("mode") as
+ | "league"
+ | "cup"
+ | null;
+ const data = await manager.getManagerCompetitions(
+ supabase,
+ user.id,
+ mode ?? undefined
+ );
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/manager/dashboard/route.ts b/app/api/manager/dashboard/route.ts
new file mode 100644
index 0000000..474378b
--- /dev/null
+++ b/app/api/manager/dashboard/route.ts
@@ -0,0 +1,15 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as manager from "@/lib/services/manager";
+
+export async function GET() {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const data = await manager.getManagerDashboard(supabase, user.id);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/master/calendar/route.ts b/app/api/master/calendar/route.ts
new file mode 100644
index 0000000..c9ceff7
--- /dev/null
+++ b/app/api/master/calendar/route.ts
@@ -0,0 +1,32 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import { getMasterCalendarMatches } from "@/lib/services/calendar";
+import { resolvePortalRole } from "@/lib/auth/resolve-portal-role";
+
+export async function GET(request: Request) {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const { role } = await resolvePortalRole(supabase, user);
+ if (role !== "league_master") {
+ return apiError(new Error("League master access required"));
+ }
+ const { searchParams } = new URL(request.url);
+ const from = searchParams.get("from");
+ const to = searchParams.get("to");
+ if (!from || !to) {
+ return apiError(new Error("from and to query params required"));
+ }
+ const data = await getMasterCalendarMatches(
+ supabase,
+ user.id,
+ false,
+ from,
+ to
+ );
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/matches/[matchId]/results/route.ts b/app/api/matches/[matchId]/results/route.ts
new file mode 100644
index 0000000..2d566a9
--- /dev/null
+++ b/app/api/matches/[matchId]/results/route.ts
@@ -0,0 +1,58 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { ApiError, apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as matches from "@/lib/services/matches";
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ matchId: string }> }
+) {
+ try {
+ const { matchId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const body = await parseJson<{
+ action: "submit" | "approve" | "set";
+ teamId?: string;
+ homeScore?: number;
+ awayScore?: number;
+ note?: string;
+ }>(request);
+
+ switch (body.action) {
+ case "submit":
+ if (body.teamId == null || body.homeScore == null || body.awayScore == null) {
+ throw new ApiError(400, "teamId, homeScore, awayScore required");
+ }
+ await matches.submitResult(
+ supabase,
+ matchId,
+ body.teamId,
+ body.homeScore,
+ body.awayScore
+ );
+ break;
+ case "approve":
+ await matches.approveResult(supabase, matchId);
+ break;
+ case "set":
+ if (body.homeScore == null || body.awayScore == null) {
+ throw new ApiError(400, "homeScore, awayScore required");
+ }
+ await matches.setResultByManager(
+ supabase,
+ matchId,
+ body.homeScore,
+ body.awayScore,
+ body.note
+ );
+ break;
+ default:
+ throw new ApiError(400, "action must be submit, approve, or set");
+ }
+
+ return apiSuccess({ ok: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/matches/[matchId]/route.ts b/app/api/matches/[matchId]/route.ts
new file mode 100644
index 0000000..82c9052
--- /dev/null
+++ b/app/api/matches/[matchId]/route.ts
@@ -0,0 +1,19 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess } from "@/lib/api/errors";
+import * as matches from "@/lib/services/matches";
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ matchId: string }> }
+) {
+ try {
+ const { matchId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await matches.getMatchDetails(supabase, matchId);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/matches/[matchId]/schedule/route.ts b/app/api/matches/[matchId]/schedule/route.ts
new file mode 100644
index 0000000..3bbaf92
--- /dev/null
+++ b/app/api/matches/[matchId]/schedule/route.ts
@@ -0,0 +1,34 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { ApiError, apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as matches from "@/lib/services/matches";
+
+export async function POST(
+ request: Request,
+ { params }: { params: Promise<{ matchId: string }> }
+) {
+ try {
+ const { matchId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const body = await parseJson<{
+ action: "propose" | "sign";
+ scheduledAt?: string;
+ teamId?: string;
+ }>(request);
+
+ if (body.action === "propose") {
+ if (!body.scheduledAt) throw new ApiError(400, "scheduledAt required");
+ await matches.proposeSchedule(supabase, matchId, body.scheduledAt);
+ } else if (body.action === "sign") {
+ if (!body.teamId) throw new ApiError(400, "teamId required");
+ await matches.signSchedule(supabase, matchId, body.teamId);
+ } else {
+ throw new ApiError(400, "action must be propose or sign");
+ }
+
+ return apiSuccess({ ok: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/players/[playerId]/route.ts b/app/api/players/[playerId]/route.ts
new file mode 100644
index 0000000..3d6ea8f
--- /dev/null
+++ b/app/api/players/[playerId]/route.ts
@@ -0,0 +1,20 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as players from "@/lib/services/players";
+
+export async function PATCH(
+ request: Request,
+ { params }: { params: Promise<{ playerId: string }> }
+) {
+ try {
+ const { playerId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const body = await parseJson<{ status: "active" | "inactive" }>(request);
+ await players.updatePlayerStatus(supabase, playerId, body.status);
+ return apiSuccess({ updated: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/players/route.ts b/app/api/players/route.ts
new file mode 100644
index 0000000..57f6aba
--- /dev/null
+++ b/app/api/players/route.ts
@@ -0,0 +1,29 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as players from "@/lib/services/players";
+
+export async function GET() {
+ try {
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const data = await players.listPlayers(supabase);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function POST(request: Request) {
+ try {
+ const supabase = await createClient();
+ const user = await requireUser(supabase);
+ const body = await parseJson<{ display_name: string; external_id?: string }>(
+ request
+ );
+ const data = await players.createPlayer(supabase, user.id, body);
+ return apiSuccess(data, 201);
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/teams/[teamId]/availability/route.ts b/app/api/teams/[teamId]/availability/route.ts
new file mode 100644
index 0000000..6d1018f
--- /dev/null
+++ b/app/api/teams/[teamId]/availability/route.ts
@@ -0,0 +1,22 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as teams from "@/lib/services/teams";
+
+export async function PUT(
+ request: Request,
+ { params }: { params: Promise<{ teamId: string }> }
+) {
+ try {
+ const { teamId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const body = await parseJson<{
+ windows: { day_of_week: number; start_time?: string; end_time?: string }[];
+ }>(request);
+ await teams.setAvailability(supabase, teamId, body.windows ?? []);
+ return apiSuccess({ saved: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/api/teams/[teamId]/route.ts b/app/api/teams/[teamId]/route.ts
new file mode 100644
index 0000000..65574ed
--- /dev/null
+++ b/app/api/teams/[teamId]/route.ts
@@ -0,0 +1,40 @@
+import { createClient } from "@/lib/supabase/server";
+import { requireUser } from "@/lib/api/auth";
+import { apiError, apiSuccess, parseJson } from "@/lib/api/errors";
+import * as teams from "@/lib/services/teams";
+
+export async function PATCH(
+ request: Request,
+ { params }: { params: Promise<{ teamId: string }> }
+) {
+ try {
+ const { teamId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ const body = await parseJson<{
+ home_stadium_name?: string;
+ logo_path?: string;
+ nickname?: string;
+ icon?: string;
+ }>(request);
+ const data = await teams.updateTeam(supabase, teamId, body);
+ return apiSuccess(data);
+ } catch (e) {
+ return apiError(e);
+ }
+}
+
+export async function DELETE(
+ _request: Request,
+ { params }: { params: Promise<{ teamId: string }> }
+) {
+ try {
+ const { teamId } = await params;
+ const supabase = await createClient();
+ await requireUser(supabase);
+ await teams.deleteTeam(supabase, teamId);
+ return apiSuccess({ deleted: true });
+ } catch (e) {
+ return apiError(e);
+ }
+}
diff --git a/app/auth/callback/route.ts b/app/auth/callback/route.ts
new file mode 100644
index 0000000..ab434cf
--- /dev/null
+++ b/app/auth/callback/route.ts
@@ -0,0 +1,21 @@
+import { NextResponse } from "next/server";
+import { createClient } from "@/lib/supabase/server";
+
+export async function GET(request: Request) {
+ const { searchParams, origin } = new URL(request.url);
+ const code = searchParams.get("code");
+ const next = searchParams.get("next") ?? "/";
+
+ if (code) {
+ const supabase = await createClient();
+ const { error } = await supabase.auth.exchangeCodeForSession(code);
+ if (error) {
+ const errUrl = new URL("/reset-password", origin);
+ errUrl.searchParams.set("error", error.message);
+ return NextResponse.redirect(errUrl);
+ }
+ }
+
+ const safeNext = next.startsWith("/") ? next : "/";
+ return NextResponse.redirect(`${origin}${safeNext}`);
+}
diff --git a/app/globals.css b/app/globals.css
new file mode 100644
index 0000000..fc3e3b3
--- /dev/null
+++ b/app/globals.css
@@ -0,0 +1,155 @@
+@import "tailwindcss";
+
+@theme inline {
+ --color-background: var(--background);
+ --color-foreground: var(--foreground);
+ --color-card: var(--card);
+ --color-card-foreground: var(--card-foreground);
+ --color-popover: var(--popover);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-primary: var(--primary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-secondary: var(--secondary);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-muted: var(--muted);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-accent: var(--accent);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-destructive: var(--destructive);
+ --color-border: var(--border);
+ --color-input: var(--input);
+ --color-ring: var(--ring);
+ --color-neon: var(--neon);
+ --color-neon-muted: var(--neon-muted);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
+ --font-sans: var(--font-barlow), ui-sans-serif, system-ui, sans-serif;
+ --font-display: var(--font-barlow-condensed), var(--font-barlow), sans-serif;
+}
+
+:root {
+ --radius: 0.75rem;
+ --background: #030303;
+ --foreground: #f4f4f5;
+ --card: #0a0a0c;
+ --card-foreground: #f4f4f5;
+ --popover: #0c0c0f;
+ --popover-foreground: #f4f4f5;
+ --primary: #c8ff4a;
+ --primary-foreground: #050505;
+ --secondary: #141416;
+ --secondary-foreground: #e4e4e7;
+ --muted: #18181b;
+ --muted-foreground: #8b8b96;
+ --accent: #1a1a1f;
+ --accent-foreground: #c8ff4a;
+ --destructive: #ff4d6d;
+ --border: #252528;
+ --input: #1c1c20;
+ --ring: #c8ff4a;
+ --neon: #c8ff4a;
+ --neon-muted: #7cb342;
+ --chart-1: #c8ff4a;
+ --chart-2: #a855f7;
+ --chart-3: #ff9124;
+ --chart-4: #22d3ee;
+ --chart-5: #f472b6;
+}
+
+* {
+ box-sizing: border-box;
+ border-color: var(--border);
+}
+
+html {
+ color-scheme: dark;
+}
+
+body {
+ background: var(--background);
+ color: var(--foreground);
+ min-height: 100vh;
+ font-family: var(--font-sans);
+ -webkit-font-smoothing: antialiased;
+}
+
+.font-display {
+ font-family: var(--font-display);
+ letter-spacing: 0.02em;
+}
+
+/* Retro grid + scanline atmosphere */
+.retro-grid {
+ position: relative;
+ isolation: isolate;
+}
+
+.retro-grid::before {
+ content: "";
+ position: fixed;
+ inset: 0;
+ z-index: -2;
+ background-image:
+ linear-gradient(color-mix(in oklab, var(--neon) 4%, transparent) 1px, transparent 1px),
+ linear-gradient(90deg, color-mix(in oklab, var(--neon) 4%, transparent) 1px, transparent 1px);
+ background-size: 40px 40px;
+ mask-image: radial-gradient(ellipse 80% 70% at 50% 0%, black 20%, transparent 75%);
+ pointer-events: none;
+}
+
+.retro-grid::after {
+ content: "";
+ position: fixed;
+ inset: 0;
+ z-index: -1;
+ background: radial-gradient(
+ ellipse 120% 80% at 50% -20%,
+ color-mix(in oklab, var(--neon) 8%, transparent),
+ transparent 55%
+ );
+ pointer-events: none;
+}
+
+.retro-card {
+ background: color-mix(in oklab, var(--card) 92%, transparent);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-xl);
+ box-shadow:
+ 0 0 0 1px color-mix(in oklab, var(--neon) 6%, transparent) inset,
+ 0 8px 32px -12px rgba(0, 0, 0, 0.65);
+ backdrop-filter: blur(8px);
+}
+
+.retro-card-glow {
+ border-color: color-mix(in oklab, var(--neon) 35%, var(--border));
+ box-shadow:
+ 0 0 0 1px color-mix(in oklab, var(--neon) 12%, transparent) inset,
+ 0 0 24px -6px color-mix(in oklab, var(--neon) 25%, transparent);
+}
+
+.neon-text {
+ color: var(--neon);
+ text-shadow: 0 0 20px color-mix(in oklab, var(--neon) 45%, transparent);
+}
+
+.neon-dot {
+ width: 5px;
+ height: 5px;
+ border-radius: 9999px;
+ background: var(--neon);
+ box-shadow: 0 0 8px var(--neon);
+}
+
+.glass-card {
+ background: var(--card);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+}
+
+.glass-card-highlight {
+ background: var(--card);
+ border: 1px solid color-mix(in oklab, var(--neon) 35%, var(--border));
+ border-radius: var(--radius-lg);
+}
diff --git a/app/layout.tsx b/app/layout.tsx
new file mode 100644
index 0000000..b9ba9c3
--- /dev/null
+++ b/app/layout.tsx
@@ -0,0 +1,37 @@
+import type { Metadata } from "next";
+import { Barlow, Barlow_Condensed } from "next/font/google";
+import "./globals.css";
+
+const barlow = Barlow({
+ variable: "--font-barlow",
+ subsets: ["latin"],
+ weight: ["400", "500", "600", "700"],
+});
+
+const barlowCondensed = Barlow_Condensed({
+ variable: "--font-barlow-condensed",
+ subsets: ["latin"],
+ weight: ["600", "700", "800", "900"],
+});
+
+export const metadata: Metadata = {
+ title: "Yaltopia FIFA — Tournament System",
+ description: "FIFA tournament holding system by Yaltopia Tech",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+
+ {children}
+
+
+ );
+}
diff --git a/app/page.tsx b/app/page.tsx
new file mode 100644
index 0000000..64472f3
--- /dev/null
+++ b/app/page.tsx
@@ -0,0 +1,73 @@
+import Link from "next/link";
+import { Trophy, ArrowRight, CalendarDays } from "lucide-react";
+import { Button } from "@/components/ui/button";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { YaltopiaFooter } from "@/components/layout/YaltopiaFooter";
+
+export default function HomePage() {
+ return (
+
+
+
+
+
+
+
+ Yaltopia · FIFA
+
+
+ Tournament OS
+
+
+ Retro-grade fixtures, standings, and squad tools — built for team
+ managers who want the hype without the clutter.
+
+
+
+
+
+
+ Team Manager
+
+
+ Sign in to view leagues, cups, your match calendar, and submit
+ issues.
+
+
+
+
+
+ Sign in
+
+
+
+
+ New manager?{" "}
+
+ Create account
+
+
+
+
+
+
+
+ Match calendar inside the manager portal
+
+
+
+
+
+
+
+ );
+}
diff --git a/components.json b/components.json
new file mode 100644
index 0000000..d06a9ae
--- /dev/null
+++ b/components.json
@@ -0,0 +1,18 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "",
+ "css": "app/globals.css",
+ "baseColor": "zinc",
+ "cssVariables": true
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib"
+ }
+}
diff --git a/components/auth/forgot-password-form.tsx b/components/auth/forgot-password-form.tsx
new file mode 100644
index 0000000..7d100a6
--- /dev/null
+++ b/components/auth/forgot-password-form.tsx
@@ -0,0 +1,146 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import Link from "next/link";
+import { createClient } from "@/lib/supabase/client";
+import { formatAuthNetworkError } from "@/lib/supabase/env";
+import { formatAuthError, isAuthRateLimitError } from "@/lib/supabase/auth-errors";
+import {
+ formatCooldownSeconds,
+ getResetEmailCooldownRemainingMs,
+ RESET_EMAIL_COOLDOWN_MS,
+ startResetEmailCooldown,
+} from "@/lib/auth/reset-email-cooldown";
+import type { PortalRole } from "@/lib/auth/roles";
+import { loginPathForRole } from "@/lib/auth/roles";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+
+function resetRedirectUrl(portal: PortalRole) {
+ const origin =
+ typeof window !== "undefined" ? window.location.origin : "";
+ const next = `/reset-password?portal=${portal}`;
+ return `${origin}/auth/callback?next=${encodeURIComponent(next)}`;
+}
+
+export function ForgotPasswordForm({ portal }: { portal: PortalRole }) {
+ const [email, setEmail] = useState("");
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+ const [sent, setSent] = useState(false);
+ const [cooldownMs, setCooldownMs] = useState(0);
+
+ const loginHref = loginPathForRole(portal);
+ const portalLabel = portal === "league_master" ? "League Master" : "Team Manager";
+
+ useEffect(() => {
+ setCooldownMs(getResetEmailCooldownRemainingMs());
+ const id = window.setInterval(() => {
+ const remaining = getResetEmailCooldownRemainingMs();
+ setCooldownMs(remaining);
+ if (remaining <= 0) window.clearInterval(id);
+ }, 1000);
+ return () => window.clearInterval(id);
+ }, [sent, error]);
+
+ async function handleSubmit(e: React.FormEvent) {
+ e.preventDefault();
+
+ const remaining = getResetEmailCooldownRemainingMs();
+ if (remaining > 0) {
+ setError(
+ `Please wait ${formatCooldownSeconds(remaining)} seconds before requesting another email.`
+ );
+ return;
+ }
+
+ setLoading(true);
+ setError(null);
+ try {
+ const supabase = createClient();
+ const { error: resetError } = await supabase.auth.resetPasswordForEmail(
+ email.trim(),
+ { redirectTo: resetRedirectUrl(portal) }
+ );
+ if (resetError) {
+ setError(formatAuthError(resetError));
+ if (isAuthRateLimitError(resetError)) {
+ startResetEmailCooldown();
+ setCooldownMs(RESET_EMAIL_COOLDOWN_MS);
+ }
+ return;
+ }
+ startResetEmailCooldown();
+ setCooldownMs(RESET_EMAIL_COOLDOWN_MS);
+ setSent(true);
+ } catch (err) {
+ setError(formatAuthNetworkError(err));
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ const submitDisabled = loading || cooldownMs > 0;
+
+ if (sent) {
+ return (
+
+
+ If an account exists for{" "}
+ {email} , we sent a reset
+ link. Check your inbox and spam folder.
+
+
+ The link opens a page to set a new password, then signs you into the{" "}
+ {portalLabel} portal.
+
+
+ Did not get it? Wait at least an hour (Supabase email limits) before
+ trying again, or use Authentication → Users in the Supabase dashboard.
+
+
+ Back to sign in
+
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/components/auth/login-form.tsx b/components/auth/login-form.tsx
new file mode 100644
index 0000000..a271b92
--- /dev/null
+++ b/components/auth/login-form.tsx
@@ -0,0 +1,157 @@
+"use client";
+
+import { useState } from "react";
+import Link from "next/link";
+import { useRouter } from "next/navigation";
+import { createClient } from "@/lib/supabase/client";
+import { formatAuthNetworkError } from "@/lib/supabase/env";
+import type { PortalRole } from "@/lib/auth/roles";
+import { PORTAL_ROUTES } from "@/lib/auth/roles";
+import {
+ ensureUserProfile,
+ isPortalRoleSchemaError,
+ resolvePortalRole,
+} from "@/lib/auth/resolve-portal-role";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { PasswordInput } from "@/components/ui/password-input";
+import { Label } from "@/components/ui/label";
+
+export function LoginForm({ expectedRole }: { expectedRole: PortalRole }) {
+ const router = useRouter();
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const [error, setError] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ async function handleSubmit(e: React.FormEvent) {
+ e.preventDefault();
+ setLoading(true);
+ setError(null);
+ try {
+ const supabase = createClient();
+ const { data: authData, error: authError } =
+ await supabase.auth.signInWithPassword({ email, password });
+ if (authError) {
+ setError(authError.message);
+ return;
+ }
+
+ const userId = authData.user?.id;
+ if (!userId) {
+ setError("Sign in failed");
+ return;
+ }
+
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) {
+ setError("Sign in failed");
+ return;
+ }
+
+ const { role, profileError } = await resolvePortalRole(supabase, user);
+
+ if (role !== expectedRole) {
+ await supabase.auth.signOut();
+ setError(
+ expectedRole === "manager"
+ ? "This account is not a Team Manager. Use the League Master sign-in URL if you are an admin."
+ : "This account is not a League Master. Use the manager sign-in page."
+ );
+ return;
+ }
+
+ if (profileError && isPortalRoleSchemaError(profileError)) {
+ setError(
+ "Database is missing portal_role. Run: npm run db:push — then try again."
+ );
+ return;
+ }
+
+ if (profileError) {
+ await ensureUserProfile(supabase, user, expectedRole);
+ }
+
+ router.push(PORTAL_ROUTES[expectedRole]);
+ router.refresh();
+ } catch (err) {
+ setError(formatAuthNetworkError(err));
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return (
+
+ );
+}
+
+export function LoginPageShell({
+ title,
+ subtitle,
+ children,
+ footer,
+}: {
+ title: string;
+ subtitle: string;
+ children: React.ReactNode;
+ footer?: React.ReactNode;
+}) {
+ return (
+
+
+
+ Yaltopia FIFA
+
+
+ {title}
+
+
{subtitle}
+
{children}
+ {footer &&
{footer}
}
+
+
+ );
+}
diff --git a/components/auth/reset-password-form.tsx b/components/auth/reset-password-form.tsx
new file mode 100644
index 0000000..637e78a
--- /dev/null
+++ b/components/auth/reset-password-form.tsx
@@ -0,0 +1,137 @@
+"use client";
+
+import { useState } from "react";
+import Link from "next/link";
+import { useRouter, useSearchParams } from "next/navigation";
+import { createClient } from "@/lib/supabase/client";
+import { formatAuthNetworkError } from "@/lib/supabase/env";
+import {
+ type PortalRole,
+ PORTAL_ROUTES,
+ loginPathForRole,
+} from "@/lib/auth/roles";
+import { Button } from "@/components/ui/button";
+import { PasswordInput } from "@/components/ui/password-input";
+import { Label } from "@/components/ui/label";
+
+function parsePortal(value: string | null): PortalRole {
+ return value === "league_master" ? "league_master" : "manager";
+}
+
+export function ResetPasswordForm() {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const portal = parsePortal(searchParams.get("portal"));
+ const urlError = searchParams.get("error");
+
+ const [password, setPassword] = useState("");
+ const [confirm, setConfirm] = useState("");
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(urlError);
+ const [done, setDone] = useState(false);
+
+ const loginHref = loginPathForRole(portal);
+
+ async function handleSubmit(e: React.FormEvent) {
+ e.preventDefault();
+ setError(null);
+
+ if (password.length < 6) {
+ setError("Password must be at least 6 characters.");
+ return;
+ }
+ if (password !== confirm) {
+ setError("Passwords do not match.");
+ return;
+ }
+
+ setLoading(true);
+ try {
+ const supabase = createClient();
+ const { error: updateError } = await supabase.auth.updateUser({
+ password,
+ });
+ if (updateError) {
+ setError(updateError.message);
+ return;
+ }
+
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+
+ if (user) {
+ const { data: profile } = await supabase
+ .from("profiles")
+ .select("portal_role")
+ .eq("id", user.id)
+ .single();
+
+ const role = (profile?.portal_role as PortalRole) ?? portal;
+ if (role !== portal) {
+ setError(
+ `This account is a ${role === "league_master" ? "League Master" : "Team Manager"} account. Use the correct reset link or sign in at the other portal.`
+ );
+ return;
+ }
+ }
+
+ setDone(true);
+ setTimeout(() => {
+ router.push(PORTAL_ROUTES[portal]);
+ router.refresh();
+ }, 1500);
+ } catch (err) {
+ setError(formatAuthNetworkError(err));
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ if (done) {
+ return (
+
+
Password updated successfully.
+
Redirecting to your dashboard…
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/components/auth/signup-form.tsx b/components/auth/signup-form.tsx
new file mode 100644
index 0000000..45981bd
--- /dev/null
+++ b/components/auth/signup-form.tsx
@@ -0,0 +1,221 @@
+"use client";
+
+import Link from "next/link";
+import { useRouter } from "next/navigation";
+import { useState } from "react";
+import { createClient } from "@/lib/supabase/client";
+import { formatAuthNetworkError } from "@/lib/supabase/env";
+import { formatAuthError, formatSignupError } from "@/lib/supabase/auth-errors";
+import { ensureUserProfile } from "@/lib/auth/resolve-portal-role";
+import type { PortalRole } from "@/lib/auth/roles";
+import { loginPathForRole, PORTAL_ROUTES } from "@/lib/auth/roles";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { PasswordInput } from "@/components/ui/password-input";
+import { Label } from "@/components/ui/label";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+
+async function signupViaApi(
+ email: string,
+ password: string,
+ displayName: string,
+ portalRole: PortalRole
+) {
+ const res = await fetch("/api/auth/signup", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ email, password, displayName, portalRole }),
+ });
+ const json = (await res.json()) as {
+ success: boolean;
+ error?: string;
+ useClient?: boolean;
+ needsEmailConfirmation?: boolean;
+ };
+ return { ok: res.ok && json.success, status: res.status, ...json };
+}
+
+export function SignupForm({
+ portalRole,
+ title,
+ description,
+}: {
+ portalRole: PortalRole;
+ title: string;
+ description: string;
+}) {
+ const router = useRouter();
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const [displayName, setDisplayName] = useState("");
+ const [error, setError] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ const loginHref = loginPathForRole(portalRole);
+ const portalLabel =
+ portalRole === "league_master" ? "League Master" : "Team Manager";
+
+ async function handleSubmit(e: React.FormEvent) {
+ e.preventDefault();
+ setLoading(true);
+ setError(null);
+
+ try {
+ const trimmedEmail = email.trim();
+ const api = await signupViaApi(
+ trimmedEmail,
+ password,
+ displayName,
+ portalRole
+ );
+
+ if (api.ok) {
+ if (api.needsEmailConfirmation) {
+ setError(
+ `Confirm your email, then sign in at ${portalLabel} login.`
+ );
+ return;
+ }
+
+ const supabase = createClient();
+ const { error: signInError } = await supabase.auth.signInWithPassword({
+ email: trimmedEmail,
+ password,
+ });
+ if (signInError) {
+ setError(
+ `Account created. Sign in at ${loginHref} (${signInError.message})`
+ );
+ return;
+ }
+ router.push(PORTAL_ROUTES[portalRole]);
+ router.refresh();
+ return;
+ }
+
+ if (api.status !== 503 && !api.useClient) {
+ setError(formatSignupError(api.error ?? "Signup failed"));
+ return;
+ }
+
+ const supabase = createClient();
+ const { data, error: authError } = await supabase.auth.signUp({
+ email: trimmedEmail,
+ password,
+ options: {
+ data: { display_name: displayName, portal_role: portalRole },
+ },
+ });
+
+ if (authError) {
+ setError(formatAuthError(authError));
+ return;
+ }
+
+ if (data.user && !data.session) {
+ setError(
+ `Confirm your email, then sign in at ${portalLabel} login.`
+ );
+ return;
+ }
+
+ if (data.user) {
+ const sync = await ensureUserProfile(
+ supabase,
+ data.user,
+ portalRole,
+ displayName
+ );
+ if (sync.error === "schema") {
+ setError(
+ "Account created but database needs an update. Run: npm run db:push — then sign in."
+ );
+ return;
+ }
+ if (!sync.ok && sync.error) {
+ setError(formatSignupError(sync.error));
+ return;
+ }
+ }
+
+ router.push(PORTAL_ROUTES[portalRole]);
+ router.refresh();
+ } catch (err) {
+ setError(formatAuthNetworkError(err));
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return (
+
+
+
+
+ Yaltopia FIFA
+
+
+ {title}
+
+ {description}
+
+
+
+
+
+ Sign in
+
+ {portalRole === "manager" && (
+ <>
+ {" · "}
+
+ Home
+
+ >
+ )}
+
+
+
+
+ );
+}
diff --git a/components/calendar/match-calendar.tsx b/components/calendar/match-calendar.tsx
new file mode 100644
index 0000000..3edb2c7
--- /dev/null
+++ b/components/calendar/match-calendar.tsx
@@ -0,0 +1,324 @@
+"use client";
+
+import { useCallback, useEffect, useMemo, useState } from "react";
+import Link from "next/link";
+import {
+ ChevronLeft,
+ ChevronRight,
+ CalendarDays,
+ Clock,
+ Loader2,
+} from "lucide-react";
+import type { CalendarMatch } from "@/lib/services/calendar";
+import {
+ addMonths,
+ buildMonthGrid,
+ endOfMonth,
+ formatMonthYear,
+ matchDisplayDate,
+ parseDateKey,
+ sameDay,
+ startOfMonth,
+ toDateKey,
+} from "@/lib/calendar/utils";
+import { apiFetch } from "@/lib/api/client";
+import { cn } from "@/lib/utils";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+
+const WEEKDAYS = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
+
+function matchWhen(m: CalendarMatch) {
+ return m.scheduled_at ?? m.proposed_scheduled_at;
+}
+
+function statusVariant(status: string) {
+ if (status === "completed" || status === "played") return "default" as const;
+ if (status === "scheduled" || status === "confirmed") return "secondary" as const;
+ return "outline" as const;
+}
+
+export function MatchCalendar({
+ apiPath,
+ title = "Match calendar",
+ description = "Plan around fixtures — days with matches glow on the grid.",
+}: {
+ apiPath: "/api/manager/calendar" | "/api/master/calendar";
+ title?: string;
+ description?: string;
+}) {
+ const [month, setMonth] = useState(() => startOfMonth(new Date()));
+ const [selected, setSelected] = useState(() => toDateKey(new Date()));
+ const [matches, setMatches] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ const load = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const from = startOfMonth(month).toISOString();
+ const to = endOfMonth(month).toISOString();
+ const data = await apiFetch(
+ `${apiPath}?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`
+ );
+ setMatches(data);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "Failed to load matches");
+ } finally {
+ setLoading(false);
+ }
+ }, [apiPath, month]);
+
+ useEffect(() => {
+ void load();
+ }, [load]);
+
+ const byDate = useMemo(() => {
+ const map = new Map();
+ for (const m of matches) {
+ const when = matchWhen(m);
+ if (!when) continue;
+ const key = toDateKey(new Date(when));
+ const list = map.get(key) ?? [];
+ list.push(m);
+ map.set(key, list);
+ }
+ return map;
+ }, [matches]);
+
+ const unscheduled = useMemo(
+ () => matches.filter((m) => !matchWhen(m)),
+ [matches]
+ );
+
+ const grid = useMemo(() => buildMonthGrid(month), [month]);
+ const selectedMatches = byDate.get(selected) ?? [];
+ const selectedDate = parseDateKey(selected);
+ const today = new Date();
+
+ const monthMatchCount = useMemo(() => {
+ let n = 0;
+ for (const [, list] of byDate) n += list.length;
+ return n;
+ }, [byDate]);
+
+ return (
+
+
+
+ Schedule
+
+
+ {title}
+
+
{description}
+
+
+
+
+
+
+
+
+ {formatMonthYear(month)}
+
+
+
+ setMonth((m) => addMonths(m, -1))}
+ aria-label="Previous month"
+ >
+
+
+ {
+ const now = startOfMonth(new Date());
+ setMonth(now);
+ setSelected(toDateKey(new Date()));
+ }}
+ >
+ Today
+
+ setMonth((m) => addMonths(m, 1))}
+ aria-label="Next month"
+ >
+
+
+
+
+
+ {loading && (
+
+
+ Loading fixtures…
+
+ )}
+
+ {error && !loading && (
+
{error}
+ )}
+
+ {!loading && !error && (
+ <>
+
+ {WEEKDAYS.map((d) => (
+
+ {d}
+
+ ))}
+
+
+
+ {grid.map((day) => {
+ const key = toDateKey(day);
+ const inMonth = day.getMonth() === month.getMonth();
+ const isSelected = key === selected;
+ const isToday = sameDay(day, today);
+ const dayMatches = byDate.get(key) ?? [];
+ const hasMatches = dayMatches.length > 0;
+
+ return (
+
setSelected(key)}
+ className={cn(
+ "group relative flex min-h-[52px] flex-col items-center justify-start rounded-xl border px-1 py-2 text-sm transition-all md:min-h-[64px]",
+ inMonth ? "border-border/80 bg-secondary/30" : "border-transparent bg-transparent opacity-35",
+ isSelected && "retro-card-glow border-neon/40 bg-neon/10",
+ !isSelected && hasMatches && "hover:border-neon/30 hover:bg-neon/5",
+ !isSelected && !hasMatches && inMonth && "hover:bg-secondary/50"
+ )}
+ >
+
+ {day.getDate()}
+
+ {hasMatches && (
+
+ {dayMatches.slice(0, 3).map((m) => (
+
+ ))}
+ {dayMatches.length > 3 && (
+
+ +{dayMatches.length - 3}
+
+ )}
+
+ )}
+
+ );
+ })}
+
+
+
+ {monthMatchCount} {" "}
+ scheduled in {formatMonthYear(month)}
+ {unscheduled.length > 0 && (
+ <>
+ {" · "}
+ {unscheduled.length} awaiting
+ date
+ >
+ )}
+
+ >
+ )}
+
+
+
+
+
+ {selectedDate.toLocaleDateString(undefined, {
+ weekday: "long",
+ month: "short",
+ day: "numeric",
+ })}
+
+
+ {selectedMatches.length === 0 ? "No matches" : `${selectedMatches.length} match${selectedMatches.length > 1 ? "es" : ""}`}
+
+
+
+ {selectedMatches.length === 0 && (
+
+ Pick a glowing day or schedule a fixture from your league.
+
+ )}
+ {selectedMatches.map((m) => (
+
+ ))}
+
+
+
+ {unscheduled.length > 0 && (
+
+
+
+
+ Date TBD
+
+
+
+ {unscheduled.map((m) => (
+
+ ))}
+
+
+ )}
+
+
+
+ );
+}
+
+function MatchCard({ match, compact }: { match: CalendarMatch; compact?: boolean }) {
+ const when = matchWhen(match);
+ const href = `/leagues/${match.league_id}/competitions/${match.competition_id}/matches/${match.id}`;
+
+ return (
+
+
+
+
+ {match.status.replace(/_/g, " ")}
+
+ {!compact && (
+ {match.league_name}
+ )}
+
+
+ {match.home_name}{" "}
+ vs {match.away_name}
+
+ {match.competition_name}
+ {matchDisplayDate(when)}
+
+
+ );
+}
diff --git a/components/competitions/competition-draft-panel.tsx b/components/competitions/competition-draft-panel.tsx
new file mode 100644
index 0000000..5efe9f0
--- /dev/null
+++ b/components/competitions/competition-draft-panel.tsx
@@ -0,0 +1,242 @@
+"use client";
+
+import { useCallback, useState } from "react";
+import { useRouter } from "next/navigation";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { TeamIconPicker } from "@/components/teams/team-icon-picker";
+import { TeamIcon } from "@/components/teams/TeamIcon";
+import { ConfirmDialog } from "@/components/ui/confirm-dialog";
+import { Trash2 } from "lucide-react";
+
+export type DraftTeam = {
+ id: string;
+ name: string;
+ nickname: string | null;
+ icon: string | null;
+ logo_path: string | null;
+};
+
+export function CompetitionDraftPanel({
+ competitionId,
+ initialTeams,
+}: {
+ competitionId: string;
+ initialTeams: DraftTeam[];
+}) {
+ const router = useRouter();
+ const [teams, setTeams] = useState(initialTeams);
+ const [name, setName] = useState("");
+ const [nickname, setNickname] = useState("");
+ const [icon, setIcon] = useState("shield");
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+ const [confirmAction, setConfirmAction] = useState<
+ | { type: "activate" }
+ | { type: "fixtures" }
+ | { type: "delete-team"; team: DraftTeam }
+ | null
+ >(null);
+
+ const refreshTeams = useCallback(async () => {
+ const list = (await api.competitions.listTeams(competitionId)) as DraftTeam[];
+ setTeams(list);
+ }, [competitionId]);
+
+ async function run(fn: () => Promise, refresh = true) {
+ setLoading(true);
+ setError(null);
+ try {
+ await fn();
+ if (refresh) {
+ await refreshTeams();
+ router.refresh();
+ }
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "Error");
+ } finally {
+ setLoading(false);
+ setConfirmAction(null);
+ }
+ }
+
+ async function handleAddTeam(e: React.FormEvent) {
+ e.preventDefault();
+ if (loading) return;
+ const trimmed = name.trim();
+ if (!trimmed) return;
+
+ setLoading(true);
+ setError(null);
+ try {
+ const created = (await api.competitions.createTeam(competitionId, {
+ name: trimmed,
+ nickname: nickname.trim() || undefined,
+ icon,
+ })) as DraftTeam;
+ setTeams((prev) => [...prev, created]);
+ setName("");
+ setNickname("");
+ setIcon("shield");
+ router.refresh();
+ } catch (err) {
+ setError(err instanceof Error ? err.message : "Failed to add team");
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return (
+
+ {error &&
{error}
}
+
+
+ setConfirmAction({ type: "activate" })}
+ >
+ Activate competition
+
+ setConfirmAction({ type: "fixtures" })}
+ >
+ Generate fixtures
+
+
+
+
+
+
+
+
+ {teams.length === 0 ? (
+
+ No teams yet. Add your first team above.
+
+ ) : (
+
+
+
+
+ Team
+ Nickname
+
+
+
+
+ {teams.map((t) => (
+
+
+
+
+ {t.name}
+
+
+
+ {t.nickname || "—"}
+
+
+
+ setConfirmAction({ type: "delete-team", team: t })
+ }
+ >
+
+
+
+
+ ))}
+
+
+
+ )}
+
+
+
!o && setConfirmAction(null)}
+ title="Activate competition?"
+ description="This snapshots league rules and opens the season. Teams cannot be added casually after activation without master access."
+ confirmLabel="Activate"
+ loading={loading}
+ variant="primary"
+ onConfirm={() =>
+ run(() => api.competitions.activate(competitionId), true)
+ }
+ />
+
+ !o && setConfirmAction(null)}
+ title="Generate fixtures?"
+ description="This creates all matches for every team. Make sure your team list is final."
+ confirmLabel="Generate"
+ loading={loading}
+ variant="primary"
+ onConfirm={() =>
+ run(() => api.competitions.generateFixtures(competitionId), true)
+ }
+ />
+
+ !o && setConfirmAction(null)}
+ title="Remove team?"
+ description={`Delete "${confirmAction?.type === "delete-team" ? confirmAction.team.name : ""}" from this competition? This cannot be undone.`}
+ confirmLabel="Delete team"
+ loading={loading}
+ onConfirm={() => {
+ if (confirmAction?.type !== "delete-team") return;
+ const id = confirmAction.team.id;
+ return run(async () => {
+ await api.teams.delete(id);
+ setTeams((prev) => prev.filter((t) => t.id !== id));
+ }, true);
+ }}
+ />
+
+ );
+}
diff --git a/components/dashboard/page-header.tsx b/components/dashboard/page-header.tsx
new file mode 100644
index 0000000..74b37d0
--- /dev/null
+++ b/components/dashboard/page-header.tsx
@@ -0,0 +1,52 @@
+"use client";
+
+import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
+
+export function PageHeader({
+ title,
+ description,
+ actions,
+ tabs,
+ activeTab,
+ onTabChange,
+}: {
+ title: string;
+ description?: string;
+ actions?: React.ReactNode;
+ tabs?: { id: string; label: string }[];
+ activeTab?: string;
+ onTabChange?: (id: string) => void;
+}) {
+ return (
+
+
+
+
+ {title}
+
+ {description && (
+
{description}
+ )}
+
+ {actions && (
+
{actions}
+ )}
+
+ {tabs && tabs.length > 0 && (
+
+
+ {tabs.map((t) => (
+
+ {t.label}
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/components/dashboard/stat-card.tsx b/components/dashboard/stat-card.tsx
new file mode 100644
index 0000000..910838c
--- /dev/null
+++ b/components/dashboard/stat-card.tsx
@@ -0,0 +1,55 @@
+import { cn } from "@/lib/utils";
+import type { LucideIcon } from "lucide-react";
+import { Card, CardContent, CardHeader } from "@/components/ui/card";
+import { Badge } from "@/components/ui/badge";
+
+export function StatCard({
+ title,
+ value,
+ subtitle,
+ icon: Icon,
+ trend,
+ trendLabel,
+}: {
+ title: string;
+ value: string | number;
+ subtitle?: string;
+ icon: LucideIcon;
+ trend?: "up" | "down" | "neutral";
+ trendLabel?: string;
+}) {
+ return (
+
+
+ {title}
+
+
+
+
+
+ {value}
+
+ {trend && trendLabel && (
+
+ {trend === "up" ? "+" : trend === "down" ? "−" : ""}
+ {trendLabel}
+
+ )}
+ {subtitle && (
+
+ {subtitle}
+
+ )}
+
+
+
+ );
+}
diff --git a/components/issues/issues-panel.tsx b/components/issues/issues-panel.tsx
new file mode 100644
index 0000000..e307a3c
--- /dev/null
+++ b/components/issues/issues-panel.tsx
@@ -0,0 +1,154 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { ConfirmDialog } from "@/components/ui/confirm-dialog";
+
+type Issue = {
+ id: string;
+ subject: string;
+ body: string;
+ status: string;
+ master_reply: string | null;
+ created_at: string;
+ leagues: { name: string } | null;
+};
+
+export function IssuesPanel({
+ leagues,
+ asMaster,
+}: {
+ leagues: { id: string; name: string }[];
+ asMaster: boolean;
+}) {
+ const [issues, setIssues] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [showConfirm, setShowConfirm] = useState(false);
+ const [pending, setPending] = useState(null);
+
+ useEffect(() => {
+ api.issues.list(asMaster).then((d) => setIssues(d as Issue[]));
+ }, [asMaster]);
+
+ async function submit(fd: FormData) {
+ setLoading(true);
+ try {
+ await api.issues.create({
+ leagueId: fd.get("league_id") as string,
+ subject: fd.get("subject") as string,
+ body: fd.get("body") as string,
+ });
+ const updated = (await api.issues.list(asMaster)) as Issue[];
+ setIssues(updated);
+ } finally {
+ setLoading(false);
+ setShowConfirm(false);
+ setPending(null);
+ }
+ }
+
+ return (
+
+
+
+ {!asMaster && (
+
+
+
+ )}
+
+
+
+
+
+
pending && submit(pending)}
+ />
+
+ );
+}
diff --git a/components/layout/AppShell.tsx b/components/layout/AppShell.tsx
new file mode 100644
index 0000000..268fcc5
--- /dev/null
+++ b/components/layout/AppShell.tsx
@@ -0,0 +1,16 @@
+import { Sidebar } from "./Sidebar";
+import { YaltopiaFooter } from "./YaltopiaFooter";
+
+export function AppShell({ children }: { children: React.ReactNode }) {
+ return (
+
+ );
+}
diff --git a/components/layout/DashboardShell.tsx b/components/layout/DashboardShell.tsx
new file mode 100644
index 0000000..54298cb
--- /dev/null
+++ b/components/layout/DashboardShell.tsx
@@ -0,0 +1,156 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import { cn } from "@/lib/utils";
+import { YaltopiaFooter } from "./YaltopiaFooter";
+import type { LucideIcon } from "lucide-react";
+import {
+ Bell,
+ Search,
+ Settings,
+ Trophy,
+ LogOut,
+} from "lucide-react";
+import { Avatar, AvatarFallback } from "@/components/ui/avatar";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { createClient } from "@/lib/supabase/client";
+import { useRouter } from "next/navigation";
+
+export type NavItem = { href: string; label: string; icon: LucideIcon };
+
+export function DashboardShell({
+ brand,
+ navItems,
+ user,
+ children,
+}: {
+ brand: string;
+ navItems: NavItem[];
+ user: { name: string; email: string };
+ children: React.ReactNode;
+}) {
+ const pathname = usePathname();
+ const router = useRouter();
+ const initials = user.name
+ .split(" ")
+ .map((n) => n[0])
+ .join("")
+ .slice(0, 2)
+ .toUpperCase();
+
+ async function signOut() {
+ const supabase = createClient();
+ await supabase.auth.signOut();
+ router.push("/");
+ router.refresh();
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ Yaltopia FIFA
+
+
+ {brand}
+
+
+
+
+
+
+ Menu
+
+ {navItems.map(({ href, label, icon: Icon }) => {
+ const active =
+ pathname === href ||
+ (href !== "/" && pathname.startsWith(href + "/"));
+ return (
+
+
+ {label}
+
+ );
+ })}
+
+
+
+
+
+
+ {initials}
+
+
+
+
{user.name}
+
+ {user.email}
+
+
+
+
void signOut()}
+ >
+
+ Sign out
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {initials}
+
+
+
+
+
{children}
+
+
+
+
+
+
+ );
+}
diff --git a/components/layout/ManagerShell.tsx b/components/layout/ManagerShell.tsx
new file mode 100644
index 0000000..ed69bc3
--- /dev/null
+++ b/components/layout/ManagerShell.tsx
@@ -0,0 +1,36 @@
+"use client";
+
+import {
+ LayoutDashboard,
+ Trophy,
+ Medal,
+ BookOpen,
+ HelpCircle,
+ MessageSquare,
+ CalendarDays,
+} from "lucide-react";
+import { DashboardShell } from "./DashboardShell";
+
+const nav = [
+ { href: "/manager", label: "Dashboard", icon: LayoutDashboard },
+ { href: "/manager/calendar", label: "Calendar", icon: CalendarDays },
+ { href: "/manager/leagues", label: "Leagues", icon: Trophy },
+ { href: "/manager/cups", label: "Cups", icon: Medal },
+ { href: "/manager/rules", label: "Rules", icon: BookOpen },
+ { href: "/manager/faq", label: "FAQ", icon: HelpCircle },
+ { href: "/manager/issues", label: "Issues", icon: MessageSquare },
+];
+
+export function ManagerShell({
+ children,
+ user,
+}: {
+ children: React.ReactNode;
+ user: { name: string; email: string };
+}) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/components/layout/MasterShell.tsx b/components/layout/MasterShell.tsx
new file mode 100644
index 0000000..8f45147
--- /dev/null
+++ b/components/layout/MasterShell.tsx
@@ -0,0 +1,32 @@
+"use client";
+
+import {
+ LayoutDashboard,
+ Trophy,
+ Users,
+ Inbox,
+ CalendarDays,
+} from "lucide-react";
+import { DashboardShell } from "./DashboardShell";
+
+const nav = [
+ { href: "/master", label: "Dashboard", icon: LayoutDashboard },
+ { href: "/master/calendar", label: "Calendar", icon: CalendarDays },
+ { href: "/master/leagues", label: "Leagues", icon: Trophy },
+ { href: "/master/players", label: "Players", icon: Users },
+ { href: "/master/issues", label: "Issues", icon: Inbox },
+];
+
+export function MasterShell({
+ children,
+ user,
+}: {
+ children: React.ReactNode;
+ user: { name: string; email: string };
+}) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/components/layout/PortalShell.tsx b/components/layout/PortalShell.tsx
new file mode 100644
index 0000000..9a35b4d
--- /dev/null
+++ b/components/layout/PortalShell.tsx
@@ -0,0 +1,61 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import { cn } from "@/lib/utils";
+import { YaltopiaFooter } from "./YaltopiaFooter";
+import type { LucideIcon } from "lucide-react";
+import { Shield } from "lucide-react";
+
+export function PortalShell({
+ brand,
+ navItems,
+ children,
+}: {
+ brand: string;
+ navItems: { href: string; label: string; icon: LucideIcon }[];
+ children: React.ReactNode;
+}) {
+ const pathname = usePathname();
+
+ return (
+
+
+
+
+
+
+
Yaltopia FIFA
+
{brand}
+
+
+
+ {navItems.map(({ href, label, icon: Icon }) => {
+ const active =
+ pathname === href || pathname.startsWith(href + "/");
+ return (
+
+
+ {label}
+
+ );
+ })}
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/components/layout/Sidebar.tsx b/components/layout/Sidebar.tsx
new file mode 100644
index 0000000..7de9906
--- /dev/null
+++ b/components/layout/Sidebar.tsx
@@ -0,0 +1,99 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import {
+ LayoutDashboard,
+ Trophy,
+ Users,
+ Settings,
+ Shield,
+} from "lucide-react";
+import { cn } from "@/lib/utils";
+
+const navItems = [
+ { href: "/leagues", label: "Leagues", icon: Trophy },
+ { href: "/players", label: "Players", icon: Users },
+];
+
+export function Sidebar() {
+ const pathname = usePathname();
+
+ return (
+
+
+
+ Yaltopia FIFA
+
+
+ {navItems.map(({ href, label, icon: Icon }) => {
+ const active =
+ pathname === href || pathname.startsWith(href + "/");
+ return (
+
+
+ {label}
+
+ );
+ })}
+
+
+ );
+}
+
+export function CompetitionSidebar({
+ leagueId,
+ competitionId,
+ showMyTeam,
+}: {
+ leagueId: string;
+ competitionId: string;
+ showMyTeam?: boolean;
+}) {
+ const pathname = usePathname();
+ const base = `/leagues/${leagueId}/competitions/${competitionId}`;
+
+ const items = [
+ { href: base, label: "Overview", icon: LayoutDashboard },
+ ...(showMyTeam
+ ? [{ href: `${base}/my-team`, label: "My Team", icon: Users }]
+ : []),
+ { href: `${base}/fixtures`, label: "Fixtures", icon: Trophy },
+ { href: `${base}/transfers`, label: "Transfers", icon: Users },
+ { href: `${base}/admin/results`, label: "Results Admin", icon: Settings },
+ ];
+
+ return (
+
+
+ {items.map(({ href, label, icon: Icon }) => {
+ const active = pathname === href;
+ return (
+
+
+ {label}
+
+ );
+ })}
+
+
+ );
+}
diff --git a/components/layout/YaltopiaFooter.tsx b/components/layout/YaltopiaFooter.tsx
new file mode 100644
index 0000000..712654c
--- /dev/null
+++ b/components/layout/YaltopiaFooter.tsx
@@ -0,0 +1,16 @@
+import Link from "next/link";
+
+export function YaltopiaFooter() {
+ return (
+
+
+ Yaltopia Tech system built with love
+
+
+ );
+}
diff --git a/components/manager/TeamCharts.tsx b/components/manager/TeamCharts.tsx
new file mode 100644
index 0000000..649d335
--- /dev/null
+++ b/components/manager/TeamCharts.tsx
@@ -0,0 +1,114 @@
+"use client";
+
+import {
+ PieChart,
+ Pie,
+ Cell,
+ LineChart,
+ Line,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ ResponsiveContainer,
+ BarChart,
+ Bar,
+} from "recharts";
+const COLORS = { W: "#34d399", D: "#fbbf24", L: "#f87171" };
+
+export function FormDonutChart({
+ data,
+}: {
+ data: { name: string; value: number }[];
+}) {
+ return (
+
+
+
+
+ {data.map((entry) => (
+ |
+ ))}
+
+
+
+
+
+ );
+}
+
+/** @deprecated Use FormDonutChart inside a Card */
+export const FormDonut = FormDonutChart;
+
+export function GoalsTrendChart({
+ data,
+}: {
+ data: { matchday: number; gf: number; ga: number }[];
+}) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function TopScorersChart({
+ data,
+ dataKey,
+ title,
+}: {
+ data: { name: string; value: number }[];
+ dataKey: string;
+ title: string;
+}) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function StatCards({
+ stats,
+}: {
+ stats: { label: string; value: string | number }[];
+}) {
+ return (
+
+ {stats.map((s) => (
+
+
{s.label}
+
{s.value}
+
+ ))}
+
+ );
+}
diff --git a/components/manager/manager-competitions-table.tsx b/components/manager/manager-competitions-table.tsx
new file mode 100644
index 0000000..fb3452a
--- /dev/null
+++ b/components/manager/manager-competitions-table.tsx
@@ -0,0 +1,117 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import Link from "next/link";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { TeamIcon } from "@/components/teams/TeamIcon";
+
+type Row = {
+ competition_id: string;
+ competition_name: string;
+ league_id: string;
+ league_name: string;
+ team_name: string;
+ team_nickname: string | null;
+ team_icon: string | null;
+ points: number;
+ goals_for: number;
+ goals_against: number;
+ goal_difference: number;
+ played: number;
+};
+
+export function ManagerCompetitionsTable({
+ title,
+ description,
+ mode,
+}: {
+ title: string;
+ description: string;
+ mode: "league" | "cup";
+}) {
+ const [rows, setRows] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ api.manager
+ .competitions(mode)
+ .then((data) => setRows(data as Row[]))
+ .catch((e) => setError(e.message))
+ .finally(() => setLoading(false));
+ }, [mode]);
+
+ return (
+
+
+
+ {error &&
{error}
}
+
+
+ {loading ? (
+ Loading…
+ ) : rows.length === 0 ? (
+
+ You are not assigned as manager to any {mode === "league" ? "league" : "cup"}{" "}
+ yet. Ask your league master to link your account to a team.
+
+ ) : (
+
+
+
+
+ Competition
+ Team
+ P
+ Pts
+ GS
+ GA
+ GD
+
+
+
+
+ {rows.map((r) => (
+
+
+ {r.competition_name}
+ {r.league_name}
+
+
+
+
+ {r.team_name}
+ {r.team_nickname && (
+
+ ({r.team_nickname})
+
+ )}
+
+
+ {r.played}
+
+ {r.points}
+
+ {r.goals_for}
+ {r.goals_against}
+ {r.goal_difference}
+
+
+ Open
+
+
+
+ ))}
+
+
+
+ )}
+
+
+ );
+}
diff --git a/components/manager/manager-dashboard-client.tsx b/components/manager/manager-dashboard-client.tsx
new file mode 100644
index 0000000..afe2fff
--- /dev/null
+++ b/components/manager/manager-dashboard-client.tsx
@@ -0,0 +1,250 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import Link from "next/link";
+import { api } from "@/lib/api/client";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { StatCard } from "@/components/dashboard/stat-card";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import {
+ Calendar,
+ Target,
+ TrendingUp,
+ Trophy,
+ ArrowUpRight,
+} from "lucide-react";
+import { FormDonutChart, GoalsTrendChart } from "@/components/manager/TeamCharts";
+
+export function ManagerDashboardClient() {
+ const [activeTab, setActiveTab] = useState("overview");
+ const [data, setData] = useState<{
+ nextFixture: Record | null;
+ recentResults: Record[];
+ stats: {
+ wins: number;
+ draws: number;
+ losses: number;
+ goalsFor: number;
+ played: number;
+ } | null;
+ } | null>(null);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ api.manager.dashboard().then(setData).finally(() => setLoading(false));
+ }, []);
+
+ const stats = data?.stats;
+ const results = (data?.recentResults ?? []) as {
+ result: string;
+ goals_for: number;
+ goals_against: number;
+ opponent_name: string;
+ scheduled_at: string;
+ }[];
+
+ const winRate =
+ stats && stats.played > 0
+ ? Math.round((stats.wins / stats.played) * 100)
+ : 0;
+
+ return (
+
+
+
+ View leagues
+
+
+
+ }
+ />
+
+ {loading ? (
+
+ {[1, 2, 3, 4].map((i) => (
+
+ ))}
+
+ ) : activeTab === "overview" ? (
+ <>
+
+ stats.losses ? "up" : "neutral"}
+ trendLabel={`${stats?.wins ?? 0}W ${stats?.draws ?? 0}D ${stats?.losses ?? 0}L`}
+ />
+
+ = 50 ? "up" : "down"}
+ trendLabel="form"
+ />
+
+
+
+
+
+
+ Result analysis
+ Form and goals trend
+
+
+ {results.length > 0 ? (
+
+ d.value > 0)}
+ />
+ ({
+ matchday: i + 1,
+ gf: r.goals_for,
+ ga: r.goals_against,
+ }))}
+ />
+
+ ) : (
+
+ Complete matches to unlock charts.
+
+ )}
+
+
+
+
+
+ Next fixture check
+ Upcoming match
+
+
+ {data?.nextFixture ? (
+
+ ) : (
+
+ No upcoming fixtures. Check{" "}
+
+ leagues
+
+ .
+
+ )}
+
+
+
+
+
+
+ Recent results
+ Latest match outcomes
+
+
+ {results.map((r, i) => (
+
+
vs {r.opponent_name}
+
+
+ {r.goals_for}-{r.goals_against}
+
+
+ {r.result}
+
+
+
+ ))}
+ {results.length === 0 && (
+ No results yet
+ )}
+
+
+ >
+ ) : (
+
+
+ {activeTab === "reports"
+ ? "Detailed reports coming soon."
+ : "Activity feed coming soon."}
+
+
+ )}
+
+ );
+}
+
+function NextFixtureCard({ fixture }: { fixture: Record }) {
+ const home = fixture.home as { name: string } | null;
+ const away = fixture.away as { name: string } | null;
+ const when =
+ (fixture.scheduled_at as string) ||
+ (fixture.proposed_scheduled_at as string);
+
+ return (
+
+
+ {home?.name} vs {" "}
+ {away?.name}
+
+ {when && (
+
+ {new Date(when).toLocaleString()}
+
+ )}
+
+ {(fixture.status as string)?.replace(/_/g, " ")}
+
+
+ );
+}
diff --git a/components/master/master-assign-panel.tsx b/components/master/master-assign-panel.tsx
new file mode 100644
index 0000000..506ce5e
--- /dev/null
+++ b/components/master/master-assign-panel.tsx
@@ -0,0 +1,68 @@
+"use client";
+
+import { useState } from "react";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+
+export function MasterAssignPanel() {
+ const [leagueId, setLeagueId] = useState("");
+ const [email, setEmail] = useState("");
+ const [message, setMessage] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ return (
+
+
+ Grant another user master access to a league by their account email.
+ Pick a league ID from the leagues page.
+
+
+
+ League ID
+ setLeagueId(e.target.value)}
+ placeholder="uuid"
+ className="mt-1 font-mono text-xs"
+ />
+
+
+ User email
+ setEmail(e.target.value)}
+ className="mt-1"
+ />
+
+ {message && (
+
+ {message}
+
+ )}
+
{
+ setLoading(true);
+ setMessage(null);
+ try {
+ await api.leagues.assignMaster(leagueId, email);
+ setMessage("Assigned successfully");
+ } catch (e) {
+ setMessage(e instanceof Error ? e.message : "Failed");
+ } finally {
+ setLoading(false);
+ }
+ }}
+ >
+ Assign master
+
+
+
+ );
+}
diff --git a/components/master/master-leagues-client.tsx b/components/master/master-leagues-client.tsx
new file mode 100644
index 0000000..ad0c80c
--- /dev/null
+++ b/components/master/master-leagues-client.tsx
@@ -0,0 +1,152 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import Link from "next/link";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { ConfirmDialog } from "@/components/ui/confirm-dialog";
+import { PageHeader } from "@/components/dashboard/page-header";
+import { Trash2, ExternalLink } from "lucide-react";
+
+type League = {
+ id: string;
+ name: string;
+ description: string | null;
+ slug: string;
+};
+
+export function MasterLeaguesClient({ initialLeagues }: { initialLeagues: League[] }) {
+ const router = useRouter();
+ const [leagues, setLeagues] = useState(initialLeagues);
+ const [name, setName] = useState("");
+ const [description, setDescription] = useState("");
+ const [loading, setLoading] = useState(false);
+ const [deleteTarget, setDeleteTarget] = useState(null);
+ const [error, setError] = useState(null);
+
+ async function handleCreate(e: React.FormEvent) {
+ e.preventDefault();
+ if (loading) return;
+ setLoading(true);
+ setError(null);
+ try {
+ const created = (await api.leagues.create({
+ name: name.trim(),
+ description: description.trim() || undefined,
+ })) as League;
+ setLeagues((prev) => [created, ...prev]);
+ setName("");
+ setDescription("");
+ router.refresh();
+ } catch (err) {
+ setError(err instanceof Error ? err.message : "Failed to create");
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return (
+
+
+
+ {error &&
{error}
}
+
+
+
+
+ Name
+ setName(e.target.value)}
+ required
+ className="mt-1"
+ placeholder="Sunday League"
+ />
+
+
+ Description
+ setDescription(e.target.value)}
+ className="mt-1"
+ />
+
+
+ {loading ? "Creating…" : "Create league"}
+
+
+
+
+
+
+
+
+
+ Name
+ ID
+ Actions
+
+
+
+ {leagues.map((l) => (
+
+ {l.name}
+
+ {l.id.slice(0, 8)}…
+
+
+
+
+
+
+ Open
+
+
+ setDeleteTarget(l)}
+ >
+
+
+
+
+
+ ))}
+
+
+
+
+
+
!o && setDeleteTarget(null)}
+ title="Delete league?"
+ description={`Permanently delete "${deleteTarget?.name}" and all competitions, teams, and matches? This cannot be undone.`}
+ confirmLabel="Delete league"
+ loading={loading}
+ onConfirm={async () => {
+ if (!deleteTarget) return;
+ setLoading(true);
+ try {
+ await api.leagues.delete(deleteTarget.id);
+ setLeagues((prev) => prev.filter((x) => x.id !== deleteTarget.id));
+ setDeleteTarget(null);
+ router.refresh();
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "Delete failed");
+ } finally {
+ setLoading(false);
+ }
+ }}
+ />
+
+ );
+}
diff --git a/components/players/players-registry.tsx b/components/players/players-registry.tsx
new file mode 100644
index 0000000..954655a
--- /dev/null
+++ b/components/players/players-registry.tsx
@@ -0,0 +1,106 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { api } from "@/lib/api/client";
+import { GlassCard } from "@/components/ui/glass-card";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+
+type Player = {
+ id: string;
+ display_name: string;
+ external_id: string | null;
+ status: string;
+};
+
+export function PlayersRegistry({ initialPlayers }: { initialPlayers: Player[] }) {
+ const router = useRouter();
+ const [players, setPlayers] = useState(initialPlayers);
+ const [loading, setLoading] = useState(false);
+
+ return (
+ <>
+
+ {
+ e.preventDefault();
+ if (loading) return;
+ const fd = new FormData(e.currentTarget);
+ setLoading(true);
+ try {
+ const created = (await api.players.create({
+ display_name: fd.get("display_name") as string,
+ external_id: (fd.get("external_id") as string) || undefined,
+ })) as Player;
+ setPlayers((prev) => [...prev, created].sort((a, b) =>
+ a.display_name.localeCompare(b.display_name)
+ ));
+ e.currentTarget.reset();
+ router.refresh();
+ } finally {
+ setLoading(false);
+ }
+ }}
+ >
+
+ Name
+
+
+
+ External ID
+
+
+
+ Add player
+
+
+
+
+
+
+
+
+
+ Name
+ Status
+ Actions
+
+
+
+ {players.map((p) => (
+
+ {p.display_name}
+ {p.status}
+
+ {
+ setLoading(true);
+ const next =
+ p.status === "active" ? "inactive" : "active";
+ await api.players.setStatus(p.id, next);
+ setPlayers((prev) =>
+ prev.map((x) =>
+ x.id === p.id ? { ...x, status: next } : x
+ )
+ );
+ setLoading(false);
+ }}
+ >
+ Toggle status
+
+
+
+ ))}
+
+
+
+
+ >
+ );
+}
diff --git a/components/standings/StandingsTable.tsx b/components/standings/StandingsTable.tsx
new file mode 100644
index 0000000..44270f3
--- /dev/null
+++ b/components/standings/StandingsTable.tsx
@@ -0,0 +1,66 @@
+import { TeamBadge } from "@/components/teams/TeamBadge";
+
+type Standing = {
+ team_id: string;
+ team_name: string;
+ logo_path: string | null;
+ played: number;
+ won: number;
+ drawn: number;
+ lost: number;
+ goals_for: number;
+ goals_against: number;
+ goal_difference: number;
+ points: number;
+};
+
+export function StandingsTable({ standings }: { standings: Standing[] }) {
+ const sorted = [...standings].sort((a, b) => {
+ if (b.points !== a.points) return b.points - a.points;
+ if (b.goal_difference !== a.goal_difference)
+ return b.goal_difference - a.goal_difference;
+ if (b.goals_for !== a.goals_for) return b.goals_for - a.goals_for;
+ return a.team_name.localeCompare(b.team_name);
+ });
+
+ return (
+
+
+
+
+ #
+ Team
+ P
+ W
+ D
+ L
+ GF
+ GA
+ GD
+ Pts
+
+
+
+ {sorted.map((row, i) => (
+
+ {i + 1}
+
+
+
+ {row.played}
+ {row.won}
+ {row.drawn}
+ {row.lost}
+ {row.goals_for}
+ {row.goals_against}
+ {row.goal_difference}
+
+ {row.points}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/components/teams/TeamBadge.tsx b/components/teams/TeamBadge.tsx
new file mode 100644
index 0000000..2e0c542
--- /dev/null
+++ b/components/teams/TeamBadge.tsx
@@ -0,0 +1,37 @@
+import Image from "next/image";
+import { getTeamLogoUrl } from "@/lib/utils";
+import { cn } from "@/lib/utils";
+
+export function TeamBadge({
+ name,
+ logoPath,
+ size = "md",
+ className,
+}: {
+ name: string;
+ logoPath?: string | null;
+ size?: "sm" | "md" | "lg";
+ className?: string;
+}) {
+ const logoUrl = getTeamLogoUrl(logoPath);
+ const sizes = { sm: 24, md: 32, lg: 48 };
+ const dim = sizes[size];
+
+ return (
+
+
+ {logoUrl ? (
+
+ ) : (
+
+ {name.slice(0, 2).toUpperCase()}
+
+ )}
+
+
{name}
+
+ );
+}
diff --git a/components/teams/TeamIcon.tsx b/components/teams/TeamIcon.tsx
new file mode 100644
index 0000000..165e224
--- /dev/null
+++ b/components/teams/TeamIcon.tsx
@@ -0,0 +1,39 @@
+import {
+ Shield,
+ Trophy,
+ Flame,
+ Zap,
+ Star,
+ Crown,
+ Swords,
+ Target,
+ type LucideIcon,
+} from "lucide-react";
+
+export const TEAM_ICON_OPTIONS = [
+ { id: "shield", label: "Shield", Icon: Shield },
+ { id: "trophy", label: "Trophy", Icon: Trophy },
+ { id: "flame", label: "Flame", Icon: Flame },
+ { id: "zap", label: "Bolt", Icon: Zap },
+ { id: "star", label: "Star", Icon: Star },
+ { id: "crown", label: "Crown", Icon: Crown },
+ { id: "swords", label: "Swords", Icon: Swords },
+ { id: "target", label: "Target", Icon: Target },
+] as const;
+
+export type TeamIconId = (typeof TEAM_ICON_OPTIONS)[number]["id"];
+
+const iconMap: Record = Object.fromEntries(
+ TEAM_ICON_OPTIONS.map((o) => [o.id, o.Icon])
+);
+
+export function TeamIcon({
+ icon,
+ className,
+}: {
+ icon?: string | null;
+ className?: string;
+}) {
+ const Icon = iconMap[icon ?? "shield"] ?? Shield;
+ return ;
+}
diff --git a/components/teams/team-icon-picker.tsx b/components/teams/team-icon-picker.tsx
new file mode 100644
index 0000000..51d8ede
--- /dev/null
+++ b/components/teams/team-icon-picker.tsx
@@ -0,0 +1,33 @@
+"use client";
+
+import { TEAM_ICON_OPTIONS } from "@/components/teams/TeamIcon";
+import { cn } from "@/lib/utils";
+
+export function TeamIconPicker({
+ value,
+ onChange,
+}: {
+ value: string;
+ onChange: (icon: string) => void;
+}) {
+ return (
+
+ {TEAM_ICON_OPTIONS.map(({ id, label, Icon }) => (
+ onChange(id)}
+ className={cn(
+ "flex h-10 w-10 items-center justify-center rounded-lg border transition-colors",
+ value === id
+ ? "border-cyan-400/50 bg-cyan-500/20 text-cyan-400"
+ : "border-white/10 bg-white/5 text-[var(--color-muted)] hover:border-white/20"
+ )}
+ >
+
+
+ ))}
+
+ );
+}
diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx
new file mode 100644
index 0000000..48ddfac
--- /dev/null
+++ b/components/ui/avatar.tsx
@@ -0,0 +1,49 @@
+"use client";
+
+import * as React from "react";
+import * as AvatarPrimitive from "@radix-ui/react-avatar";
+import { cn } from "@/lib/utils";
+
+const Avatar = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+Avatar.displayName = AvatarPrimitive.Root.displayName;
+
+const AvatarImage = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarImage.displayName = AvatarPrimitive.Image.displayName;
+
+const AvatarFallback = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
+
+export { Avatar, AvatarImage, AvatarFallback };
diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx
new file mode 100644
index 0000000..fe83c7e
--- /dev/null
+++ b/components/ui/badge.tsx
@@ -0,0 +1,37 @@
+import * as React from "react";
+import { cva, type VariantProps } from "class-variance-authority";
+import { cn } from "@/lib/utils";
+
+const badgeVariants = cva(
+ "inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-medium transition-colors",
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground",
+ secondary:
+ "border-transparent bg-secondary text-secondary-foreground",
+ outline: "text-foreground border-border",
+ success:
+ "border-transparent bg-emerald-500/15 text-emerald-400",
+ destructive:
+ "border-transparent bg-red-500/15 text-red-400",
+ warning:
+ "border-transparent bg-amber-500/15 text-amber-400",
+ },
+ },
+ defaultVariants: { variant: "default" },
+ }
+);
+
+export interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return (
+
+ );
+}
+
+export { Badge, badgeVariants };
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
new file mode 100644
index 0000000..1d667ce
--- /dev/null
+++ b/components/ui/button.tsx
@@ -0,0 +1,56 @@
+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-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive/15 text-red-400 hover:bg-destructive/25 border border-destructive/30",
+ outline:
+ "border border-border bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-foreground underline-offset-4 hover:underline",
+ neon:
+ "rounded-full bg-primary font-semibold text-primary-foreground shadow-[0_0_24px_-6px_var(--neon)] hover:bg-primary/90",
+ danger:
+ "bg-destructive/15 text-red-400 hover:bg-destructive/25 border border-destructive/30",
+ },
+ size: {
+ default: "h-9 px-4 py-2",
+ sm: "h-8 rounded-md px-3 text-xs",
+ lg: "h-10 rounded-md px-8",
+ icon: "h-9 w-9",
+ },
+ },
+ defaultVariants: { variant: "default", size: "default" },
+ }
+);
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button";
+ return (
+
+ );
+ }
+);
+Button.displayName = "Button";
+
+export { Button, buttonVariants };
diff --git a/components/ui/card.tsx b/components/ui/card.tsx
new file mode 100644
index 0000000..3bb3029
--- /dev/null
+++ b/components/ui/card.tsx
@@ -0,0 +1,75 @@
+import * as React from "react";
+import { cn } from "@/lib/utils";
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+Card.displayName = "Card";
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardHeader.displayName = "CardHeader";
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardTitle.displayName = "CardTitle";
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardDescription.displayName = "CardDescription";
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardContent.displayName = "CardContent";
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardFooter.displayName = "CardFooter";
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
diff --git a/components/ui/confirm-dialog.tsx b/components/ui/confirm-dialog.tsx
new file mode 100644
index 0000000..5bb2e82
--- /dev/null
+++ b/components/ui/confirm-dialog.tsx
@@ -0,0 +1,60 @@
+"use client";
+
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+
+export function ConfirmDialog({
+ open,
+ onOpenChange,
+ title,
+ description,
+ confirmLabel = "Confirm",
+ cancelLabel = "Cancel",
+ variant = "danger",
+ loading,
+ onConfirm,
+}: {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ title: string;
+ description: string;
+ confirmLabel?: string;
+ cancelLabel?: string;
+ variant?: "danger" | "primary";
+ loading?: boolean;
+ onConfirm: () => void | Promise;
+}) {
+ return (
+
+
+
+ {title}
+ {description}
+
+
+ onOpenChange(false)}
+ disabled={loading}
+ >
+ {cancelLabel}
+
+ void onConfirm()}
+ >
+ {loading ? "Please wait…" : confirmLabel}
+
+
+
+
+ );
+}
diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx
new file mode 100644
index 0000000..3502039
--- /dev/null
+++ b/components/ui/dialog.tsx
@@ -0,0 +1,108 @@
+"use client";
+
+import * as React from "react";
+import * as DialogPrimitive from "@radix-ui/react-dialog";
+import { X } from "lucide-react";
+import { cn } from "@/lib/utils";
+
+const Dialog = DialogPrimitive.Root;
+const DialogTrigger = DialogPrimitive.Trigger;
+const DialogPortal = DialogPrimitive.Portal;
+const DialogClose = DialogPrimitive.Close;
+
+const DialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
+
+const DialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+
+
+
+));
+DialogContent.displayName = DialogPrimitive.Content.displayName;
+
+function DialogHeader({
+ className,
+ ...props
+}: React.HTMLAttributes) {
+ return (
+
+ );
+}
+
+function DialogFooter({
+ className,
+ ...props
+}: React.HTMLAttributes) {
+ return (
+
+ );
+}
+
+function DialogTitle({
+ className,
+ ...props
+}: React.ComponentPropsWithoutRef) {
+ return (
+
+ );
+}
+
+function DialogDescription({
+ className,
+ ...props
+}: React.ComponentPropsWithoutRef) {
+ return (
+
+ );
+}
+
+export {
+ Dialog,
+ DialogTrigger,
+ DialogContent,
+ DialogHeader,
+ DialogFooter,
+ DialogTitle,
+ DialogDescription,
+ DialogClose,
+};
diff --git a/components/ui/glass-card.tsx b/components/ui/glass-card.tsx
new file mode 100644
index 0000000..17ec936
--- /dev/null
+++ b/components/ui/glass-card.tsx
@@ -0,0 +1,44 @@
+import { cn } from "@/lib/utils";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+
+interface GlassCardProps extends React.HTMLAttributes {
+ highlight?: boolean;
+ title?: string;
+ description?: string;
+}
+
+/** @deprecated Prefer Card directly — kept for gradual migration */
+export function GlassCard({
+ className,
+ highlight,
+ title,
+ description,
+ children,
+ ...props
+}: GlassCardProps) {
+ return (
+
+ {(title || description) && (
+
+ {title && {title} }
+ {description && {description} }
+
+ )}
+
+ {children}
+
+
+ );
+}
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
new file mode 100644
index 0000000..793da97
--- /dev/null
+++ b/components/ui/input.tsx
@@ -0,0 +1,19 @@
+import * as React from "react";
+import { cn } from "@/lib/utils";
+
+const Input = React.forwardRef>(
+ ({ className, type, ...props }, ref) => (
+
+ )
+);
+Input.displayName = "Input";
+
+export { Input };
diff --git a/components/ui/label.tsx b/components/ui/label.tsx
new file mode 100644
index 0000000..304f05a
--- /dev/null
+++ b/components/ui/label.tsx
@@ -0,0 +1,22 @@
+"use client";
+
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { cn } from "@/lib/utils";
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+Label.displayName = LabelPrimitive.Root.displayName;
+
+export { Label };
diff --git a/components/ui/password-input.tsx b/components/ui/password-input.tsx
new file mode 100644
index 0000000..c3507ab
--- /dev/null
+++ b/components/ui/password-input.tsx
@@ -0,0 +1,43 @@
+"use client";
+
+import * as React from "react";
+import { Eye, EyeOff } from "lucide-react";
+import { cn } from "@/lib/utils";
+import { Input } from "@/components/ui/input";
+import { Button } from "@/components/ui/button";
+
+const PasswordInput = React.forwardRef<
+ HTMLInputElement,
+ Omit, "type">
+>(({ className, ...props }, ref) => {
+ const [visible, setVisible] = React.useState(false);
+
+ return (
+
+
+ setVisible((v) => !v)}
+ tabIndex={-1}
+ aria-label={visible ? "Hide password" : "Show password"}
+ >
+ {visible ? (
+
+ ) : (
+
+ )}
+
+
+ );
+});
+PasswordInput.displayName = "PasswordInput";
+
+export { PasswordInput };
diff --git a/components/ui/separator.tsx b/components/ui/separator.tsx
new file mode 100644
index 0000000..c334b4c
--- /dev/null
+++ b/components/ui/separator.tsx
@@ -0,0 +1,30 @@
+"use client";
+
+import * as React from "react";
+import * as SeparatorPrimitive from "@radix-ui/react-separator";
+import { cn } from "@/lib/utils";
+
+const Separator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(
+ (
+ { className, orientation = "horizontal", decorative = true, ...props },
+ ref
+ ) => (
+
+ )
+);
+Separator.displayName = SeparatorPrimitive.Root.displayName;
+
+export { Separator };
diff --git a/components/ui/tabs.tsx b/components/ui/tabs.tsx
new file mode 100644
index 0000000..d44856d
--- /dev/null
+++ b/components/ui/tabs.tsx
@@ -0,0 +1,51 @@
+"use client";
+
+import * as React from "react";
+import * as TabsPrimitive from "@radix-ui/react-tabs";
+import { cn } from "@/lib/utils";
+
+const Tabs = TabsPrimitive.Root;
+
+const TabsList = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsList.displayName = TabsPrimitive.List.displayName;
+
+const TabsTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+
+const TabsContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsContent.displayName = TabsPrimitive.Content.displayName;
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/docs/CLOUDFLARE_DEPLOY.md b/docs/CLOUDFLARE_DEPLOY.md
new file mode 100644
index 0000000..b5bbd64
--- /dev/null
+++ b/docs/CLOUDFLARE_DEPLOY.md
@@ -0,0 +1,107 @@
+# Deploy Yaltopia FIFA to Cloudflare
+
+This app uses [**OpenNext**](https://opennext.js.org/cloudflare) (`@opennextjs/cloudflare`) to run Next.js 15 on **Cloudflare Workers** (not legacy `next-on-pages`).
+
+## Prerequisites
+
+1. [Cloudflare account](https://dash.cloudflare.com/sign-up)
+2. Node.js 20+
+3. Wrangler logged in: `npx wrangler login`
+
+## 1. Install dependencies
+
+```bash
+npm install
+```
+
+## 2. Environment variables (build + runtime)
+
+`NEXT_PUBLIC_*` values are embedded at **build time**. Before `npm run deploy`, ensure they are set:
+
+**Option A — local deploy (use your `.env.local`):**
+
+```bash
+# .env.local must exist with:
+# NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
+# NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... or sb_publishable_...
+npm run deploy
+```
+
+**Option B — Cloudflare Dashboard (Git CI):**
+
+Workers & Pages → your project → **Settings** → **Variables and secrets**:
+
+| Name | Type | Notes |
+|------|------|--------|
+| `NEXT_PUBLIC_SUPABASE_URL` | Plaintext | Build + production |
+| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Plaintext | Build + production |
+
+Mark both as available at **build** time if the UI offers it.
+
+## 3. Supabase Auth redirect URLs
+
+In Supabase → **Authentication** → **URL configuration**, add your Cloudflare URLs:
+
+```
+https://yaltopia-fifa..workers.dev/auth/callback
+https://yaltopia-fifa..workers.dev/reset-password
+https://your-custom-domain.com/auth/callback
+https://your-custom-domain.com/reset-password
+```
+
+Set **Site URL** to your production URL (e.g. `https://yaltopia-fifa.your-account.workers.dev`).
+
+## 4. Deploy from CLI
+
+```bash
+npm run deploy
+```
+
+First run creates the Worker `yaltopia-fifa` and prints a `*.workers.dev` URL.
+
+## 5. Preview locally (Workers runtime)
+
+```bash
+cp .dev.vars.example .dev.vars
+npm run preview
+```
+
+Opens on `http://localhost:8787` (approx.) — closer to production than `next dev`.
+
+## 6. Custom domain
+
+1. Cloudflare Dashboard → **Workers & Pages** → **yaltopia-fifa**
+2. **Settings** → **Domains & routes** → **Add custom domain**
+3. Update Supabase redirect URLs to use that domain
+
+## 7. GitHub / GitLab CI (optional)
+
+Connect the repo in Cloudflare:
+
+1. **Workers & Pages** → **Create** → **Workers** → **Connect to Git**
+2. Build command: `npm run deploy` or split:
+ - Build: `npx opennextjs-cloudflare build`
+ - Deploy: `npx opennextjs-cloudflare deploy`
+3. Add the same `NEXT_PUBLIC_*` variables in project settings
+
+## Scripts
+
+| Script | Purpose |
+|--------|---------|
+| `npm run dev` | Next.js dev server (Node) |
+| `npm run preview` | Build + local Workers preview |
+| `npm run deploy` | Build + deploy to Cloudflare |
+| `npm run upload` | Build + upload version only |
+
+## Troubleshooting
+
+- **Build fails on env**: Set `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` before build.
+- **Auth redirect error**: Add exact callback URLs in Supabase (include `/auth/callback`).
+- **Images**: Team logos use `next/image` + Supabase storage; `wrangler.jsonc` enables the `IMAGES` binding.
+- **League Master URLs**: Still `/login/master`, `/master`, etc. — not linked on the public home page.
+
+## Project files
+
+- `wrangler.jsonc` — Worker name, compatibility, assets
+- `open-next.config.ts` — OpenNext Cloudflare adapter
+- `public/_headers` — static asset caching
diff --git a/docs/LEAGUE_MASTER_ACCESS.md b/docs/LEAGUE_MASTER_ACCESS.md
new file mode 100644
index 0000000..c982078
--- /dev/null
+++ b/docs/LEAGUE_MASTER_ACCESS.md
@@ -0,0 +1,58 @@
+# League Master portal (hidden from public UI)
+
+The home page and manager signup only show the **Team Manager** flow. League Master access is via direct URLs (bookmark these).
+
+| Page | URL |
+|------|-----|
+| Sign in | `/login/master` |
+| Forgot password | `/forgot-password/master` |
+| Sign up | `/signup/master` |
+| Dashboard | `/master` |
+| Leagues | `/master/leagues` |
+| Players | `/master/players` |
+| Issues inbox | `/master/issues` |
+
+## Layout (same shell as managers)
+
+```
+┌──────────────┬─────────────────────────────────────────────┐
+│ Sidebar │ Top bar: search · notifications · settings │
+│ · Dashboard ├─────────────────────────────────────────────┤
+│ · Leagues │ Page title + actions │
+│ · Players │ KPI cards (4-col grid) │
+│ · Issues │ Main content cards / tables │
+│ │ Footer (Yaltopia link) │
+│ [User] │ │
+│ Sign out │ │
+└──────────────┴─────────────────────────────────────────────┘
+```
+
+Accounts must have `profiles.portal_role = 'league_master'`.
+
+## Signup 500 / "Database error saving new user"
+
+If master signup fails with **500**, Supabase could not insert the `profiles` row (auth trigger).
+
+1. Apply migrations: `npm run db:push` (includes `20250524000008_fix_signup_trigger.sql`)
+2. Or paste `supabase/scripts/fix-signup-trigger.sql` into the SQL Editor and run it
+3. Add to `.env.local` for reliable dev signup (never commit):
+
+```env
+SUPABASE_SERVICE_ROLE_KEY=... # Dashboard → Settings → API → service_role
+SUPABASE_AUTO_CONFIRM_EMAIL=true # optional: skip email confirm in dev
+```
+
+Restart `npm run dev`, then try `/signup/master` again.
+
+**Team Manager forgot password:** `/forgot-password/manager` (linked from manager sign-in).
+
+### Supabase Auth redirect URLs
+
+Add these under **Authentication → URL configuration → Redirect URLs**:
+
+```
+http://localhost:3000/auth/callback
+http://localhost:3000/reset-password
+```
+
+Use your production domain in production (e.g. `https://your-app.com/auth/callback`).
diff --git a/docs/PASSWORD_RESET.md b/docs/PASSWORD_RESET.md
new file mode 100644
index 0000000..86a6731
--- /dev/null
+++ b/docs/PASSWORD_RESET.md
@@ -0,0 +1,54 @@
+# Password reset & email rate limits (429)
+
+## Why you see 429
+
+`resetPasswordForEmail` sends mail through **Supabase Auth**. Free and trial projects have **strict limits** (often about **2 auth emails per hour** for the whole project). Clicking “Send reset link” many times while testing quickly hits **429 Too Many Requests**.
+
+The app cannot remove that limit; only waiting, using the dashboard, custom SMTP, or an admin password update can help.
+
+## What to do right now
+
+### 1. Use an email you already received
+
+If you requested a reset earlier, search **inbox and spam** for “Reset your password” from Supabase. The link may still work for a while.
+
+### 2. Wait, then try once
+
+Wait **at least 60 minutes**, then submit **one** request. The forgot-password page enforces a short client cooldown so repeated clicks do not make the limit worse.
+
+### 3. Reset from Supabase Dashboard
+
+1. [Supabase Dashboard](https://supabase.com/dashboard) → your project
+2. **Authentication** → **Users**
+3. Find the user → **⋮** → **Send password recovery** (or update password if your plan shows that option)
+
+### 4. Local dev: set password without email
+
+Add the **service_role** key to `.env.local` (never commit it):
+
+```env
+SUPABASE_SERVICE_ROLE_KEY=eyJ... # Dashboard → Settings → API
+```
+
+Then:
+
+```bash
+npm run auth:reset-password -- you@example.com YourNewPassword
+```
+
+Sign in at `/login/manager` or `/login/master`.
+
+## Redirect URLs (required for email links)
+
+**Authentication** → **URL configuration**:
+
+- Site URL: `http://localhost:3000` (dev) or your production URL
+- Redirect URLs must include:
+ - `http://localhost:3000/auth/callback`
+ - `http://localhost:3000/**` (or explicit production URLs)
+
+Password reset flow: email → `/auth/callback?next=/reset-password?portal=manager` → set new password.
+
+## Raise limits long-term
+
+**Project Settings** → **Authentication** → **SMTP Settings**: configure custom SMTP (Resend, SendGrid, etc.) for higher volume and your own domain.
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..bbd17c7
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,14 @@
+import { dirname } from "path";
+import { fileURLToPath } from "url";
+import { FlatCompat } from "@eslint/eslintrc";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+});
+
+const eslintConfig = [...compat.extends("next/core-web-vitals", "next/typescript")];
+
+export default eslintConfig;
diff --git a/lib/api/auth.ts b/lib/api/auth.ts
new file mode 100644
index 0000000..90e86de
--- /dev/null
+++ b/lib/api/auth.ts
@@ -0,0 +1,17 @@
+import type { SupabaseClient, User } from "@supabase/supabase-js";
+import { ApiError } from "./errors";
+
+export async function requireUser(
+ supabase: SupabaseClient
+): Promise {
+ const {
+ data: { user },
+ error,
+ } = await supabase.auth.getUser();
+
+ if (error || !user) {
+ throw new ApiError(401, "Unauthorized — sign in required");
+ }
+
+ return user;
+}
diff --git a/lib/api/client.ts b/lib/api/client.ts
new file mode 100644
index 0000000..40fbf03
--- /dev/null
+++ b/lib/api/client.ts
@@ -0,0 +1,213 @@
+/** Browser client for Next.js API routes */
+
+type ApiResponse = { success: true; data: T } | { success: false; error: string };
+
+export async function apiFetch(
+ path: string,
+ options?: RequestInit
+): Promise {
+ const res = await fetch(path, {
+ ...options,
+ headers: {
+ "Content-Type": "application/json",
+ ...options?.headers,
+ },
+ credentials: "same-origin",
+ });
+
+ let json: ApiResponse;
+ try {
+ json = await res.json();
+ } catch {
+ throw new Error(`API ${path} returned invalid JSON (${res.status})`);
+ }
+
+ if (!json.success) {
+ throw new Error(json.error || `Request failed (${res.status})`);
+ }
+
+ return json.data;
+}
+
+export const api = {
+ health: () => apiFetch<{ status: string; supabase: boolean }>("/api/health"),
+
+ leagues: {
+ list: () => apiFetch("/api/leagues"),
+ create: (body: { name: string; description?: string }) =>
+ apiFetch("/api/leagues", {
+ method: "POST",
+ body: JSON.stringify(body),
+ }),
+ get: (leagueId: string) => apiFetch(`/api/leagues/${leagueId}`),
+ createCompetition: (
+ leagueId: string,
+ body: { name: string; tournament_mode: "league" | "cup"; timezone?: string }
+ ) =>
+ apiFetch(`/api/leagues/${leagueId}/competitions`, {
+ method: "POST",
+ body: JSON.stringify(body),
+ }),
+ saveRules: (leagueId: string, rules: object) =>
+ apiFetch(`/api/leagues/${leagueId}/rules`, {
+ method: "POST",
+ body: JSON.stringify({ rules }),
+ }),
+ delete: (leagueId: string) =>
+ apiFetch(`/api/leagues/${leagueId}`, { method: "DELETE" }),
+ assignMaster: (leagueId: string, email: string) =>
+ apiFetch(`/api/leagues/${leagueId}/masters`, {
+ method: "POST",
+ body: JSON.stringify({ email }),
+ }),
+ listMasters: (leagueId: string) =>
+ apiFetch(`/api/leagues/${leagueId}/masters`),
+ },
+
+ competitions: {
+ get: (id: string) => apiFetch(`/api/competitions/${id}`),
+ activate: (id: string) =>
+ apiFetch(`/api/competitions/${id}/activate`, { method: "POST" }),
+ generateFixtures: (id: string) =>
+ apiFetch(`/api/competitions/${id}/fixtures`, { method: "POST" }),
+ standings: (id: string) =>
+ apiFetch(`/api/competitions/${id}/standings`),
+ matches: (id: string) =>
+ apiFetch(`/api/competitions/${id}/matches`),
+ pendingResults: (id: string) =>
+ apiFetch(`/api/competitions/${id}/pending-results`),
+ transfers: (id: string) =>
+ apiFetch(`/api/competitions/${id}/transfers`),
+ dashboard: (id: string) =>
+ apiFetch<{ results: unknown[]; playerStats: unknown[] }>(
+ `/api/competitions/${id}/dashboard`
+ ),
+ listTeams: (id: string) =>
+ apiFetch(`/api/competitions/${id}/teams`),
+ createTeam: (
+ id: string,
+ body: { name: string; nickname?: string; icon?: string }
+ ) =>
+ apiFetch(`/api/competitions/${id}/teams`, {
+ method: "POST",
+ body: JSON.stringify(body),
+ }),
+ addRoster: (
+ id: string,
+ body: { teamId: string; playerId: string }
+ ) =>
+ apiFetch(`/api/competitions/${id}/roster`, {
+ method: "POST",
+ body: JSON.stringify(body),
+ }),
+ transfer: (
+ id: string,
+ body: { playerId: string; fromTeamId: string; toTeamId: string }
+ ) =>
+ apiFetch(`/api/competitions/${id}/transfers`, {
+ method: "POST",
+ body: JSON.stringify(body),
+ }),
+ },
+
+ teams: {
+ delete: (teamId: string) =>
+ apiFetch(`/api/teams/${teamId}`, { method: "DELETE" }),
+ update: (teamId: string, body: { home_stadium_name?: string; logo_path?: string; nickname?: string; icon?: string }) =>
+ apiFetch(`/api/teams/${teamId}`, {
+ method: "PATCH",
+ body: JSON.stringify(body),
+ }),
+ setAvailability: (
+ teamId: string,
+ windows: { day_of_week: number; start_time?: string; end_time?: string }[]
+ ) =>
+ apiFetch(`/api/teams/${teamId}/availability`, {
+ method: "PUT",
+ body: JSON.stringify({ windows }),
+ }),
+ },
+
+ players: {
+ list: () => apiFetch("/api/players"),
+ create: (body: { display_name: string; external_id?: string }) =>
+ apiFetch("/api/players", {
+ method: "POST",
+ body: JSON.stringify(body),
+ }),
+ setStatus: (playerId: string, status: "active" | "inactive") =>
+ apiFetch(`/api/players/${playerId}`, {
+ method: "PATCH",
+ body: JSON.stringify({ status }),
+ }),
+ },
+
+ matches: {
+ get: (matchId: string) => apiFetch(`/api/matches/${matchId}`),
+ proposeSchedule: (matchId: string, scheduledAt: string) =>
+ apiFetch(`/api/matches/${matchId}/schedule`, {
+ method: "POST",
+ body: JSON.stringify({ action: "propose", scheduledAt }),
+ }),
+ signSchedule: (matchId: string, teamId: string) =>
+ apiFetch(`/api/matches/${matchId}/schedule`, {
+ method: "POST",
+ body: JSON.stringify({ action: "sign", teamId }),
+ }),
+ submitResult: (
+ matchId: string,
+ body: { teamId: string; homeScore: number; awayScore: number }
+ ) =>
+ apiFetch(`/api/matches/${matchId}/results`, {
+ method: "POST",
+ body: JSON.stringify({ action: "submit", ...body }),
+ }),
+ approveResult: (matchId: string) =>
+ apiFetch(`/api/matches/${matchId}/results`, {
+ method: "POST",
+ body: JSON.stringify({ action: "approve" }),
+ }),
+ setResult: (
+ matchId: string,
+ body: { homeScore: number; awayScore: number; note?: string }
+ ) =>
+ apiFetch(`/api/matches/${matchId}/results`, {
+ method: "POST",
+ body: JSON.stringify({ action: "set", ...body }),
+ }),
+ },
+
+ manager: {
+ dashboard: () => apiFetch("/api/manager/dashboard"),
+ competitions: (mode?: "league" | "cup") =>
+ apiFetch(
+ `/api/manager/competitions${mode ? `?mode=${mode}` : ""}`
+ ),
+ calendar: (from: string, to: string) =>
+ apiFetch(
+ `/api/manager/calendar?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`
+ ),
+ },
+
+ master: {
+ calendar: (from: string, to: string) =>
+ apiFetch(
+ `/api/master/calendar?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`
+ ),
+ },
+
+ issues: {
+ list: (asMaster?: boolean) =>
+ apiFetch(`/api/issues${asMaster ? "?as=master" : ""}`),
+ create: (body: {
+ leagueId: string;
+ competitionId?: string;
+ subject: string;
+ body: string;
+ }) =>
+ apiFetch("/api/issues", {
+ method: "POST",
+ body: JSON.stringify(body),
+ }),
+ },
+};
diff --git a/lib/api/errors.ts b/lib/api/errors.ts
new file mode 100644
index 0000000..c223cdb
--- /dev/null
+++ b/lib/api/errors.ts
@@ -0,0 +1,36 @@
+import { NextResponse } from "next/server";
+
+export class ApiError extends Error {
+ constructor(
+ public status: number,
+ message: string
+ ) {
+ super(message);
+ this.name = "ApiError";
+ }
+}
+
+export function apiSuccess(data: T, status = 200) {
+ return NextResponse.json({ success: true, data }, { status });
+}
+
+export function apiError(error: unknown) {
+ if (error instanceof ApiError) {
+ return NextResponse.json(
+ { success: false, error: error.message },
+ { status: error.status }
+ );
+ }
+ const message =
+ error instanceof Error ? error.message : "Internal server error";
+ console.error("[API]", error);
+ return NextResponse.json({ success: false, error: message }, { status: 500 });
+}
+
+export async function parseJson(request: Request): Promise {
+ try {
+ return (await request.json()) as T;
+ } catch {
+ throw new ApiError(400, "Invalid JSON body");
+ }
+}
diff --git a/lib/auth/profile.ts b/lib/auth/profile.ts
new file mode 100644
index 0000000..5e71960
--- /dev/null
+++ b/lib/auth/profile.ts
@@ -0,0 +1,46 @@
+import { createClient } from "@/lib/supabase/server";
+import type { PortalRole } from "./roles";
+import { resolvePortalRole } from "./resolve-portal-role";
+
+export async function getCurrentProfile() {
+ const supabase = await createClient();
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ if (!user) return null;
+
+ const { role } = await resolvePortalRole(supabase, user);
+
+ const { data: profile } = await supabase
+ .from("profiles")
+ .select("id, display_name, avatar_url, portal_role")
+ .eq("id", user.id)
+ .maybeSingle();
+
+ return {
+ user,
+ profile: {
+ id: user.id,
+ display_name:
+ profile?.display_name ??
+ user.user_metadata?.display_name ??
+ user.email?.split("@")[0] ??
+ null,
+ avatar_url: profile?.avatar_url ?? null,
+ portal_role: role,
+ },
+ };
+}
+
+export async function requirePortalRole(role: PortalRole) {
+ const ctx = await getCurrentProfile();
+ if (!ctx?.user) return { ok: false as const, reason: "auth" as const };
+ if (ctx.profile.portal_role !== role) {
+ return {
+ ok: false as const,
+ reason: "role" as const,
+ actual: ctx.profile.portal_role,
+ };
+ }
+ return { ok: true as const, ...ctx };
+}
\ No newline at end of file
diff --git a/lib/auth/reset-email-cooldown.ts b/lib/auth/reset-email-cooldown.ts
new file mode 100644
index 0000000..bcddbf1
--- /dev/null
+++ b/lib/auth/reset-email-cooldown.ts
@@ -0,0 +1,23 @@
+/** Client-only guard so users do not hammer Supabase auth email endpoints. */
+
+const STORAGE_KEY = "yaltopia_forgot_password_cooldown_until";
+/** Minimum wait between reset attempts from this browser */
+export const RESET_EMAIL_COOLDOWN_MS = 120_000;
+
+export function getResetEmailCooldownRemainingMs(): number {
+ if (typeof window === "undefined") return 0;
+ const until = Number(localStorage.getItem(STORAGE_KEY) || 0);
+ return Math.max(0, until - Date.now());
+}
+
+export function startResetEmailCooldown(): void {
+ if (typeof window === "undefined") return;
+ localStorage.setItem(
+ STORAGE_KEY,
+ String(Date.now() + RESET_EMAIL_COOLDOWN_MS)
+ );
+}
+
+export function formatCooldownSeconds(ms: number): number {
+ return Math.ceil(ms / 1000);
+}
diff --git a/lib/auth/resolve-portal-role.ts b/lib/auth/resolve-portal-role.ts
new file mode 100644
index 0000000..cab1ac6
--- /dev/null
+++ b/lib/auth/resolve-portal-role.ts
@@ -0,0 +1,95 @@
+import type { SupabaseClient, User } from "@supabase/supabase-js";
+import type { PortalRole } from "./roles";
+
+export function portalRoleFromMetadata(user: User): PortalRole | null {
+ const raw = user.user_metadata?.portal_role;
+ if (raw === "league_master" || raw === "manager") return raw;
+ return null;
+}
+
+export function isPortalRoleSchemaError(message?: string): boolean {
+ if (!message) return false;
+ const m = message.toLowerCase();
+ return (
+ m.includes("portal_role") &&
+ (m.includes("column") || m.includes("schema cache") || m.includes("does not exist"))
+ );
+}
+
+/**
+ * Resolves portal role from profiles table, then auth metadata, then default (manager).
+ */
+export async function resolvePortalRole(
+ supabase: SupabaseClient,
+ user: User
+): Promise<{
+ role: PortalRole;
+ profileMissing: boolean;
+ profileError?: string;
+}> {
+ const { data, error } = await supabase
+ .from("profiles")
+ .select("portal_role")
+ .eq("id", user.id)
+ .maybeSingle();
+
+ if (!error && data?.portal_role) {
+ const role = data.portal_role as PortalRole;
+ if (role === "league_master" || role === "manager") {
+ return { role, profileMissing: false };
+ }
+ }
+
+ const fromMeta = portalRoleFromMetadata(user);
+ if (fromMeta) {
+ return {
+ role: fromMeta,
+ profileMissing: Boolean(error),
+ profileError: error?.message,
+ };
+ }
+
+ return {
+ role: "manager",
+ profileMissing: Boolean(error),
+ profileError: error?.message,
+ };
+}
+
+/** Sync profile row + portal_role after signup or when column was missing. */
+export async function ensureUserProfile(
+ supabase: SupabaseClient,
+ user: User,
+ portalRole: PortalRole,
+ displayName?: string
+): Promise<{ ok: boolean; error?: string }> {
+ const { error: rpcError } = await supabase.rpc("ensure_user_profile", {
+ p_display_name:
+ displayName ??
+ user.user_metadata?.display_name ??
+ user.email?.split("@")[0] ??
+ null,
+ p_portal_role: portalRole,
+ });
+
+ if (!rpcError) return { ok: true };
+
+ if (isPortalRoleSchemaError(rpcError.message)) {
+ return { ok: false, error: "schema" };
+ }
+
+ const { error: upsertError } = await supabase.from("profiles").upsert(
+ {
+ id: user.id,
+ display_name:
+ displayName ??
+ user.user_metadata?.display_name ??
+ user.email?.split("@")[0],
+ portal_role: portalRole,
+ },
+ { onConflict: "id" }
+ );
+
+ if (!upsertError) return { ok: true };
+ return { ok: false, error: upsertError.message };
+}
diff --git a/lib/auth/roles.ts b/lib/auth/roles.ts
new file mode 100644
index 0000000..fb339bc
--- /dev/null
+++ b/lib/auth/roles.ts
@@ -0,0 +1,10 @@
+export type PortalRole = "league_master" | "manager";
+
+export const PORTAL_ROUTES: Record = {
+ league_master: "/master",
+ manager: "/manager",
+};
+
+export function loginPathForRole(role: PortalRole) {
+ return role === "league_master" ? "/login/master" : "/login/manager";
+}
diff --git a/lib/calendar/utils.ts b/lib/calendar/utils.ts
new file mode 100644
index 0000000..fb3ba49
--- /dev/null
+++ b/lib/calendar/utils.ts
@@ -0,0 +1,61 @@
+export function startOfMonth(d: Date) {
+ return new Date(d.getFullYear(), d.getMonth(), 1);
+}
+
+export function endOfMonth(d: Date) {
+ return new Date(d.getFullYear(), d.getMonth() + 1, 0, 23, 59, 59, 999);
+}
+
+export function addMonths(d: Date, n: number) {
+ return new Date(d.getFullYear(), d.getMonth() + n, 1);
+}
+
+export function sameDay(a: Date, b: Date) {
+ return (
+ a.getFullYear() === b.getFullYear() &&
+ a.getMonth() === b.getMonth() &&
+ a.getDate() === b.getDate()
+ );
+}
+
+export function toDateKey(d: Date) {
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
+}
+
+export function parseDateKey(key: string) {
+ const [y, m, day] = key.split("-").map(Number);
+ return new Date(y, m - 1, day);
+}
+
+/** Monday-first calendar grid cells (includes leading/trailing days). */
+export function buildMonthGrid(month: Date): Date[] {
+ const start = startOfMonth(month);
+ const end = endOfMonth(month);
+ const startPad = (start.getDay() + 6) % 7;
+ const cells: Date[] = [];
+ const gridStart = new Date(start);
+ gridStart.setDate(start.getDate() - startPad);
+
+ for (let i = 0; i < 42; i++) {
+ const cell = new Date(gridStart);
+ cell.setDate(gridStart.getDate() + i);
+ cells.push(cell);
+ if (i >= 27 && cell >= end && cell.getDay() === 0) break;
+ }
+ return cells;
+}
+
+export function formatMonthYear(d: Date) {
+ return d.toLocaleDateString("en-US", { month: "long", year: "numeric" });
+}
+
+export function matchDisplayDate(iso: string | null) {
+ if (!iso) return "TBD";
+ return new Date(iso).toLocaleString(undefined, {
+ weekday: "short",
+ month: "short",
+ day: "numeric",
+ hour: "2-digit",
+ minute: "2-digit",
+ });
+}
diff --git a/lib/content/faq.ts b/lib/content/faq.ts
new file mode 100644
index 0000000..50f1e67
--- /dev/null
+++ b/lib/content/faq.ts
@@ -0,0 +1,18 @@
+export const MANAGER_FAQ = [
+ {
+ q: "How do I submit a match result?",
+ a: "Open the fixture from your dashboard or competition page, enter the score, and submit. Both managers must submit matching scores before the league master approves.",
+ },
+ {
+ q: "How do transfers work?",
+ a: "Players must exist in the global registry first. Your league master adds them, then you can register transfers between teams in the competition transfers page.",
+ },
+ {
+ q: "Who approves disputed scores?",
+ a: "The league master reviews pending results and can approve matching submissions or set an official score.",
+ },
+ {
+ q: "How do I report a problem?",
+ a: "Use the Issues page to send a message to your league master. Include your league and a clear subject.",
+ },
+];
diff --git a/lib/middleware/portal.ts b/lib/middleware/portal.ts
new file mode 100644
index 0000000..2b195b0
--- /dev/null
+++ b/lib/middleware/portal.ts
@@ -0,0 +1,20 @@
+import type { PortalRole } from "@/lib/auth/roles";
+import { PORTAL_ROUTES, loginPathForRole } from "@/lib/auth/roles";
+
+export function pathForRole(role: PortalRole | null | undefined) {
+ if (role === "league_master") return PORTAL_ROUTES.league_master;
+ if (role === "manager") return PORTAL_ROUTES.manager;
+ return "/";
+}
+
+export function loginForPath(pathname: string) {
+ if (pathname.startsWith("/master")) return loginPathForRole("league_master");
+ if (pathname.startsWith("/manager")) return loginPathForRole("manager");
+ return "/login/manager";
+}
+
+export function roleForPath(pathname: string): PortalRole | null {
+ if (pathname.startsWith("/master")) return "league_master";
+ if (pathname.startsWith("/manager")) return "manager";
+ return null;
+}
diff --git a/lib/rules/schema.ts b/lib/rules/schema.ts
new file mode 100644
index 0000000..0721484
--- /dev/null
+++ b/lib/rules/schema.ts
@@ -0,0 +1,39 @@
+import { z } from "zod";
+
+export const cupFormatSchema = z.object({
+ legs: z.enum(["single", "home_away"]).default("single"),
+ third_place_match: z.boolean().default(false),
+ seeding: z.enum(["random", "manual"]).default("random"),
+});
+
+export const leagueRulesSchema = z.object({
+ points_win: z.number().int().min(0).default(3),
+ points_draw: z.number().int().min(0).default(1),
+ round_robin_format: z.enum(["single", "double"]).default("double"),
+ transfer_policy: z.enum(["anytime", "window"]).default("anytime"),
+ auto_qualify_count: z.number().int().min(0).default(1),
+ strict_availability: z.boolean().default(false),
+ result_approval_required: z.boolean().default(true),
+ cup_format: cupFormatSchema.default({}),
+});
+
+export type LeagueRules = z.infer;
+
+export const defaultLeagueRules: LeagueRules = {
+ points_win: 3,
+ points_draw: 1,
+ round_robin_format: "double",
+ transfer_policy: "anytime",
+ auto_qualify_count: 1,
+ strict_availability: false,
+ result_approval_required: true,
+ cup_format: {
+ legs: "single",
+ third_place_match: false,
+ seeding: "random",
+ },
+};
+
+export function parseLeagueRules(data: unknown): LeagueRules {
+ return leagueRulesSchema.parse({ ...defaultLeagueRules, ...(data as object) });
+}
diff --git a/lib/services/calendar.ts b/lib/services/calendar.ts
new file mode 100644
index 0000000..3f55aa1
--- /dev/null
+++ b/lib/services/calendar.ts
@@ -0,0 +1,192 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+
+export type CalendarMatch = {
+ id: string;
+ competition_id: string;
+ competition_name: string;
+ league_id: string;
+ league_name: string;
+ scheduled_at: string | null;
+ proposed_scheduled_at: string | null;
+ status: string;
+ result_status: string | null;
+ home_team_id: string;
+ away_team_id: string;
+ home_name: string;
+ away_name: string;
+ my_team_ids: string[];
+};
+
+function pickMatchDate(m: {
+ scheduled_at: string | null;
+ proposed_scheduled_at: string | null;
+}) {
+ return m.scheduled_at ?? m.proposed_scheduled_at;
+}
+
+export async function getManagerCalendarMatches(
+ supabase: SupabaseClient,
+ userId: string,
+ rangeStart: string,
+ rangeEnd: string
+): Promise {
+ const { data: memberships } = await supabase
+ .from("team_members")
+ .select("team_id")
+ .eq("user_id", userId)
+ .eq("role", "manager");
+
+ const teamIds = memberships?.map((m) => m.team_id) ?? [];
+ if (teamIds.length === 0) return [];
+
+ const teamFilter = teamIds.join(",");
+ const { data: matches, error } = await supabase
+ .from("matches")
+ .select(
+ `id, competition_id, status, result_status, scheduled_at, proposed_scheduled_at,
+ home_team_id, away_team_id,
+ home:home_team_id(id, name),
+ away:away_team_id(id, name),
+ competitions(id, name, league_id, leagues(name))`
+ )
+ .or(`home_team_id.in.(${teamFilter}),away_team_id.in.(${teamFilter})`)
+ .order("scheduled_at", { ascending: true });
+
+ if (error) throw new Error(error.message);
+
+ const start = new Date(rangeStart).getTime();
+ const end = new Date(rangeEnd).getTime();
+
+ return (matches ?? [])
+ .map((m) => {
+ const when = pickMatchDate(m);
+ const comp = m.competitions as {
+ id: string;
+ name: string;
+ league_id: string;
+ leagues: { name: string } | null;
+ } | null;
+ const home = m.home as { id: string; name: string };
+ const away = m.away as { id: string; name: string };
+ return {
+ id: m.id,
+ competition_id: comp?.id ?? m.competition_id,
+ competition_name: comp?.name ?? "Competition",
+ league_id: comp?.league_id ?? "",
+ league_name: comp?.leagues?.name ?? "League",
+ scheduled_at: m.scheduled_at,
+ proposed_scheduled_at: m.proposed_scheduled_at,
+ status: m.status,
+ result_status: m.result_status,
+ home_team_id: m.home_team_id,
+ away_team_id: m.away_team_id,
+ home_name: home?.name ?? "Home",
+ away_name: away?.name ?? "Away",
+ my_team_ids: teamIds.filter(
+ (tid) => tid === m.home_team_id || tid === m.away_team_id
+ ),
+ _when: when,
+ };
+ })
+ .filter((m) => {
+ if (!m._when) return true;
+ const t = new Date(m._when).getTime();
+ return t >= start && t <= end;
+ })
+ .map(({ _when, ...rest }) => rest);
+}
+
+export async function getMasterCalendarMatches(
+ supabase: SupabaseClient,
+ userId: string,
+ isGlobalMaster: boolean,
+ rangeStart: string,
+ rangeEnd: string
+): Promise {
+ let competitionIds: string[] = [];
+
+ if (isGlobalMaster) {
+ const { data } = await supabase.from("competitions").select("id");
+ competitionIds = data?.map((c) => c.id) ?? [];
+ } else {
+ const { data: owned } = await supabase
+ .from("leagues")
+ .select("id")
+ .eq("created_by", userId);
+ const leagueIds = owned?.map((l) => l.id) ?? [];
+
+ const { data: assigned } = await supabase
+ .from("league_masters")
+ .select("league_id")
+ .eq("user_id", userId);
+ const allLeagueIds = [
+ ...new Set([
+ ...leagueIds,
+ ...(assigned?.map((a) => a.league_id) ?? []),
+ ]),
+ ];
+
+ if (allLeagueIds.length === 0) return [];
+
+ const { data: comps } = await supabase
+ .from("competitions")
+ .select("id")
+ .in("league_id", allLeagueIds);
+ competitionIds = comps?.map((c) => c.id) ?? [];
+ }
+
+ if (competitionIds.length === 0) return [];
+
+ const { data: matches, error } = await supabase
+ .from("matches")
+ .select(
+ `id, competition_id, status, result_status, scheduled_at, proposed_scheduled_at,
+ home_team_id, away_team_id,
+ home:home_team_id(id, name),
+ away:away_team_id(id, name),
+ competitions(id, name, league_id, leagues(name))`
+ )
+ .in("competition_id", competitionIds)
+ .order("scheduled_at", { ascending: true });
+
+ if (error) throw new Error(error.message);
+
+ const start = new Date(rangeStart).getTime();
+ const end = new Date(rangeEnd).getTime();
+
+ return (matches ?? [])
+ .map((m) => {
+ const when = pickMatchDate(m);
+ const comp = m.competitions as {
+ id: string;
+ name: string;
+ league_id: string;
+ leagues: { name: string } | null;
+ } | null;
+ const home = m.home as { id: string; name: string };
+ const away = m.away as { id: string; name: string };
+ return {
+ id: m.id,
+ competition_id: comp?.id ?? m.competition_id,
+ competition_name: comp?.name ?? "Competition",
+ league_id: comp?.league_id ?? "",
+ league_name: comp?.leagues?.name ?? "League",
+ scheduled_at: m.scheduled_at,
+ proposed_scheduled_at: m.proposed_scheduled_at,
+ status: m.status,
+ result_status: m.result_status,
+ home_team_id: m.home_team_id,
+ away_team_id: m.away_team_id,
+ home_name: home?.name ?? "Home",
+ away_name: away?.name ?? "Away",
+ my_team_ids: [],
+ _when: when,
+ };
+ })
+ .filter((m) => {
+ if (!m._when) return true;
+ const t = new Date(m._when).getTime();
+ return t >= start && t <= end;
+ })
+ .map(({ _when, ...rest }) => rest);
+}
diff --git a/lib/services/issues.ts b/lib/services/issues.ts
new file mode 100644
index 0000000..e89a13a
--- /dev/null
+++ b/lib/services/issues.ts
@@ -0,0 +1,61 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+
+export async function listIssuesForUser(
+ supabase: SupabaseClient,
+ userId: string,
+ asMaster: boolean
+) {
+ let query = supabase
+ .from("support_issues")
+ .select("*, leagues(name), competitions(name)")
+ .order("created_at", { ascending: false });
+
+ if (!asMaster) {
+ query = query.eq("submitted_by", userId);
+ }
+
+ const { data, error } = await query;
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function createIssue(
+ supabase: SupabaseClient,
+ userId: string,
+ input: {
+ leagueId: string;
+ competitionId?: string;
+ subject: string;
+ body: string;
+ }
+) {
+ const { data, error } = await supabase
+ .from("support_issues")
+ .insert({
+ league_id: input.leagueId,
+ competition_id: input.competitionId ?? null,
+ submitted_by: userId,
+ subject: input.subject,
+ body: input.body,
+ })
+ .select()
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function updateIssueStatus(
+ supabase: SupabaseClient,
+ issueId: string,
+ status: "open" | "in_progress" | "resolved",
+ masterReply?: string
+) {
+ const { error } = await supabase
+ .from("support_issues")
+ .update({
+ status,
+ ...(masterReply !== undefined ? { master_reply: masterReply } : {}),
+ })
+ .eq("id", issueId);
+ if (error) throw new Error(error.message);
+}
diff --git a/lib/services/leagues.ts b/lib/services/leagues.ts
new file mode 100644
index 0000000..2b4457d
--- /dev/null
+++ b/lib/services/leagues.ts
@@ -0,0 +1,181 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+import { defaultLeagueRules } from "@/lib/rules/schema";
+import { slugify } from "@/lib/utils";
+
+export async function deleteLeague(supabase: SupabaseClient, leagueId: string) {
+ const { error } = await supabase.from("leagues").delete().eq("id", leagueId);
+ if (error) throw new Error(error.message);
+}
+
+export async function listLeaguesForMaster(
+ supabase: SupabaseClient,
+ userId: string,
+ isGlobalMaster: boolean
+) {
+ if (isGlobalMaster) return listLeagues(supabase);
+
+ const { data: owned } = await supabase
+ .from("leagues")
+ .select("*")
+ .eq("created_by", userId);
+
+ const { data: assigned } = await supabase
+ .from("league_masters")
+ .select("leagues(*)")
+ .eq("user_id", userId);
+
+ type LeagueRow = Awaited>[number];
+ const merged: LeagueRow[] = [
+ ...(owned ?? []),
+ ...((assigned ?? [])
+ .map((a) => a.leagues as LeagueRow | null)
+ .filter(Boolean) as LeagueRow[]),
+ ];
+ return Array.from(new Map(merged.map((l) => [l.id, l])).values()).sort(
+ (a, b) =>
+ new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
+ );
+}
+
+export async function listLeagues(supabase: SupabaseClient) {
+ const { data, error } = await supabase
+ .from("leagues")
+ .select("*")
+ .order("created_at", { ascending: false });
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function createLeague(
+ supabase: SupabaseClient,
+ userId: string,
+ input: { name: string; description?: string }
+) {
+ const { data: league, error } = await supabase
+ .from("leagues")
+ .insert({
+ name: input.name,
+ slug: slugify(input.name) + "-" + Date.now().toString(36),
+ description: input.description || null,
+ created_by: userId,
+ })
+ .select()
+ .single();
+
+ if (error) throw new Error(error.message);
+
+ await supabase.from("league_rules").insert({
+ league_id: league.id,
+ version: 1,
+ rules: defaultLeagueRules,
+ created_by: userId,
+ });
+
+ return league;
+}
+
+export async function getLeague(supabase: SupabaseClient, leagueId: string) {
+ const { data, error } = await supabase
+ .from("leagues")
+ .select("*, competitions(*)")
+ .eq("id", leagueId)
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function createCompetition(
+ supabase: SupabaseClient,
+ userId: string,
+ leagueId: string,
+ input: {
+ name: string;
+ tournament_mode: "league" | "cup";
+ timezone?: string;
+ }
+) {
+ const { data, error } = await supabase
+ .from("competitions")
+ .insert({
+ league_id: leagueId,
+ name: input.name,
+ tournament_mode: input.tournament_mode,
+ timezone: input.timezone || "UTC",
+ created_by: userId,
+ })
+ .select()
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function getCompetition(
+ supabase: SupabaseClient,
+ competitionId: string
+) {
+ const { data, error } = await supabase
+ .from("competitions")
+ .select("*, leagues(id, name)")
+ .eq("id", competitionId)
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function activateCompetition(
+ supabase: SupabaseClient,
+ competitionId: string
+) {
+ const { error } = await supabase.rpc("activate_competition", {
+ p_competition_id: competitionId,
+ });
+ if (error) throw new Error(error.message);
+}
+
+export async function generateFixtures(
+ supabase: SupabaseClient,
+ competitionId: string,
+ mode: "league" | "cup"
+) {
+ const fn = mode === "cup" ? "generate_cup_bracket" : "generate_league_fixtures";
+ const { data, error } = await supabase.rpc(fn, {
+ p_competition_id: competitionId,
+ });
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function getStandings(
+ supabase: SupabaseClient,
+ competitionId: string
+) {
+ const { data, error } = await supabase
+ .from("competition_standings")
+ .select("*")
+ .eq("competition_id", competitionId);
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function saveLeagueRules(
+ supabase: SupabaseClient,
+ userId: string,
+ leagueId: string,
+ rules: object
+) {
+ const { data: latest } = await supabase
+ .from("league_rules")
+ .select("version")
+ .eq("league_id", leagueId)
+ .order("version", { ascending: false })
+ .limit(1)
+ .single();
+
+ const { error } = await supabase.from("league_rules").insert({
+ league_id: leagueId,
+ version: (latest?.version ?? 0) + 1,
+ rules,
+ created_by: userId,
+ });
+ if (error) throw new Error(error.message);
+}
diff --git a/lib/services/manager.ts b/lib/services/manager.ts
new file mode 100644
index 0000000..96bdcdd
--- /dev/null
+++ b/lib/services/manager.ts
@@ -0,0 +1,133 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+
+export type ManagerCompetitionRow = {
+ competition_id: string;
+ competition_name: string;
+ league_id: string;
+ league_name: string;
+ tournament_mode: "league" | "cup";
+ team_id: string;
+ team_name: string;
+ team_nickname: string | null;
+ team_icon: string | null;
+ points: number;
+ goals_for: number;
+ goals_against: number;
+ goal_difference: number;
+ played: number;
+};
+
+export async function getManagerCompetitions(
+ supabase: SupabaseClient,
+ userId: string,
+ mode?: "league" | "cup"
+) {
+ const { data: memberships, error: mErr } = await supabase
+ .from("team_members")
+ .select("team_id, teams(id, name, nickname, icon, competition_id)")
+ .eq("user_id", userId)
+ .eq("role", "manager");
+
+ if (mErr) throw new Error(mErr.message);
+ if (!memberships?.length) return [] as ManagerCompetitionRow[];
+
+ const rows: ManagerCompetitionRow[] = [];
+
+ for (const m of memberships) {
+ const team = m.teams as {
+ id: string;
+ name: string;
+ nickname: string | null;
+ icon: string | null;
+ competition_id: string;
+ };
+ if (!team?.competition_id) continue;
+
+ const { data: comp } = await supabase
+ .from("competitions")
+ .select("id, name, tournament_mode, league_id, leagues(name)")
+ .eq("id", team.competition_id)
+ .single();
+
+ if (!comp) continue;
+ if (mode && comp.tournament_mode !== mode) continue;
+
+ const { data: standing } = await supabase
+ .from("competition_standings")
+ .select("points, goals_for, goals_against, goal_difference, played")
+ .eq("competition_id", team.competition_id)
+ .eq("team_id", team.id)
+ .maybeSingle();
+
+ const league = comp.leagues as { name: string } | null;
+
+ rows.push({
+ competition_id: comp.id,
+ competition_name: comp.name,
+ league_id: comp.league_id,
+ league_name: league?.name ?? "League",
+ tournament_mode: comp.tournament_mode as "league" | "cup",
+ team_id: team.id,
+ team_name: team.name,
+ team_nickname: team.nickname,
+ team_icon: team.icon,
+ points: standing?.points ?? 0,
+ goals_for: standing?.goals_for ?? 0,
+ goals_against: standing?.goals_against ?? 0,
+ goal_difference: standing?.goal_difference ?? 0,
+ played: standing?.played ?? 0,
+ });
+ }
+
+ return rows;
+}
+
+export async function getManagerDashboard(
+ supabase: SupabaseClient,
+ userId: string
+) {
+ const { data: memberships } = await supabase
+ .from("team_members")
+ .select("team_id, teams(competition_id)")
+ .eq("user_id", userId)
+ .eq("role", "manager");
+
+ const teamIds = memberships?.map((m) => m.team_id) ?? [];
+ if (teamIds.length === 0) {
+ return { nextFixture: null, recentResults: [], stats: null };
+ }
+
+ const teamFilter = teamIds.join(",");
+ const { data: nextFixture } = await supabase
+ .from("matches")
+ .select(
+ `id, scheduled_at, proposed_scheduled_at, status, home_team_id, away_team_id,
+ home:home_team_id(name, nickname, icon),
+ away:away_team_id(name, nickname, icon),
+ competitions(name, leagues(name))`
+ )
+ .or(`home_team_id.in.(${teamFilter}),away_team_id.in.(${teamFilter})`)
+ .in("status", ["scheduled", "schedule_pending", "schedule_confirmed"])
+ .order("scheduled_at", { ascending: true, nullsFirst: false })
+ .limit(1)
+ .maybeSingle();
+
+ const { data: recentResults } = await supabase
+ .from("team_match_results")
+ .select("*")
+ .in("team_id", teamIds)
+ .order("scheduled_at", { ascending: false })
+ .limit(8);
+
+ const wins = recentResults?.filter((r) => r.result === "W").length ?? 0;
+ const draws = recentResults?.filter((r) => r.result === "D").length ?? 0;
+ const losses = recentResults?.filter((r) => r.result === "L").length ?? 0;
+ const goalsFor =
+ recentResults?.reduce((s, r) => s + (r.goals_for ?? 0), 0) ?? 0;
+
+ return {
+ nextFixture,
+ recentResults: recentResults ?? [],
+ stats: { wins, draws, losses, goalsFor, played: recentResults?.length ?? 0 },
+ };
+}
diff --git a/lib/services/masters.ts b/lib/services/masters.ts
new file mode 100644
index 0000000..e2714ef
--- /dev/null
+++ b/lib/services/masters.ts
@@ -0,0 +1,38 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+
+export async function assignLeagueMaster(
+ supabase: SupabaseClient,
+ leagueId: string,
+ userId: string,
+ assignedBy: string
+) {
+ const { error } = await supabase.from("league_masters").upsert({
+ league_id: leagueId,
+ user_id: userId,
+ assigned_by: assignedBy,
+ });
+ if (error) throw new Error(error.message);
+}
+
+export async function listLeagueMasters(
+ supabase: SupabaseClient,
+ leagueId: string
+) {
+ const { data, error } = await supabase
+ .from("league_masters")
+ .select("user_id, profiles(display_name)")
+ .eq("league_id", leagueId);
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function getUserIdByEmail(
+ supabase: SupabaseClient,
+ email: string
+) {
+ const { data, error } = await supabase.rpc("get_user_id_by_email", {
+ p_email: email,
+ });
+ if (error) throw new Error(error.message);
+ return data as string | null;
+}
diff --git a/lib/services/matches.ts b/lib/services/matches.ts
new file mode 100644
index 0000000..0fffde7
--- /dev/null
+++ b/lib/services/matches.ts
@@ -0,0 +1,132 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+
+export async function listMatches(
+ supabase: SupabaseClient,
+ competitionId: string
+) {
+ const { data, error } = await supabase
+ .from("matches")
+ .select(
+ `*, home:home_team_id(id, name, logo_path), away:away_team_id(id, name, logo_path)`
+ )
+ .eq("competition_id", competitionId)
+ .order("matchday")
+ .order("round");
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function getMatch(supabase: SupabaseClient, matchId: string) {
+ const { data, error } = await supabase
+ .from("matches")
+ .select(
+ `*, home:home_team_id(id, name, logo_path), away:away_team_id(id, name, logo_path)`
+ )
+ .eq("id", matchId)
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function getMatchDetails(
+ supabase: SupabaseClient,
+ matchId: string
+) {
+ const [match, submissions, signatures] = await Promise.all([
+ getMatch(supabase, matchId),
+ supabase
+ .from("match_result_submissions")
+ .select("*, teams(name)")
+ .eq("match_id", matchId),
+ supabase
+ .from("match_signatures")
+ .select("team_id, signed_at, teams(name)")
+ .eq("match_id", matchId),
+ ]);
+ return {
+ match,
+ submissions: submissions.data ?? [],
+ signatures: signatures.data ?? [],
+ };
+}
+
+export async function proposeSchedule(
+ supabase: SupabaseClient,
+ matchId: string,
+ scheduledAt: string
+) {
+ const { error } = await supabase.rpc("propose_match_schedule", {
+ p_match_id: matchId,
+ p_scheduled_at: scheduledAt,
+ });
+ if (error) throw new Error(error.message);
+}
+
+export async function signSchedule(
+ supabase: SupabaseClient,
+ matchId: string,
+ teamId: string
+) {
+ const { error } = await supabase.rpc("sign_match_schedule", {
+ p_match_id: matchId,
+ p_team_id: teamId,
+ });
+ if (error) throw new Error(error.message);
+}
+
+export async function submitResult(
+ supabase: SupabaseClient,
+ matchId: string,
+ teamId: string,
+ homeScore: number,
+ awayScore: number
+) {
+ const { error } = await supabase.rpc("submit_match_result", {
+ p_match_id: matchId,
+ p_team_id: teamId,
+ p_home_score: homeScore,
+ p_away_score: awayScore,
+ });
+ if (error) throw new Error(error.message);
+}
+
+export async function approveResult(
+ supabase: SupabaseClient,
+ matchId: string
+) {
+ const { error } = await supabase.rpc("approve_match_result", {
+ p_match_id: matchId,
+ });
+ if (error) throw new Error(error.message);
+}
+
+export async function setResultByManager(
+ supabase: SupabaseClient,
+ matchId: string,
+ homeScore: number,
+ awayScore: number,
+ note?: string
+) {
+ const { error } = await supabase.rpc("set_match_result_by_manager", {
+ p_match_id: matchId,
+ p_home_score: homeScore,
+ p_away_score: awayScore,
+ p_note: note ?? null,
+ });
+ if (error) throw new Error(error.message);
+}
+
+export async function listPendingResults(
+ supabase: SupabaseClient,
+ competitionId: string
+) {
+ const { data, error } = await supabase
+ .from("matches")
+ .select(
+ `*, home:home_team_id(name, logo_path), away:away_team_id(name, logo_path)`
+ )
+ .eq("competition_id", competitionId)
+ .in("result_status", ["pending_approval", "disputed"]);
+ if (error) throw new Error(error.message);
+ return data;
+}
diff --git a/lib/services/players.ts b/lib/services/players.ts
new file mode 100644
index 0000000..e35dfc9
--- /dev/null
+++ b/lib/services/players.ts
@@ -0,0 +1,112 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+
+export async function listPlayers(supabase: SupabaseClient) {
+ const { data, error } = await supabase
+ .from("players")
+ .select("*")
+ .order("display_name");
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function createPlayer(
+ supabase: SupabaseClient,
+ userId: string,
+ input: { display_name: string; external_id?: string }
+) {
+ const { data, error } = await supabase
+ .from("players")
+ .insert({
+ display_name: input.display_name,
+ external_id: input.external_id || null,
+ created_by: userId,
+ })
+ .select()
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function updatePlayerStatus(
+ supabase: SupabaseClient,
+ playerId: string,
+ status: "active" | "inactive"
+) {
+ const { error } = await supabase
+ .from("players")
+ .update({ status })
+ .eq("id", playerId);
+ if (error) throw new Error(error.message);
+}
+
+export async function addToRoster(
+ supabase: SupabaseClient,
+ userId: string,
+ input: { teamId: string; competitionId: string; playerId: string }
+) {
+ const { error: rosterError } = await supabase.from("team_roster").insert({
+ team_id: input.teamId,
+ player_id: input.playerId,
+ competition_id: input.competitionId,
+ });
+ if (rosterError) throw new Error(rosterError.message);
+
+ await supabase.from("roster_events").insert({
+ team_id: input.teamId,
+ player_id: input.playerId,
+ competition_id: input.competitionId,
+ event_type: "add",
+ registered_by: userId,
+ });
+}
+
+export async function registerTransfer(
+ supabase: SupabaseClient,
+ userId: string,
+ input: {
+ competitionId: string;
+ playerId: string;
+ fromTeamId: string;
+ toTeamId: string;
+ }
+) {
+ const { error: tError } = await supabase.from("transfers").insert({
+ competition_id: input.competitionId,
+ player_id: input.playerId,
+ from_team_id: input.fromTeamId,
+ to_team_id: input.toTeamId,
+ registered_by: userId,
+ status: "completed",
+ });
+ if (tError) throw new Error(tError.message);
+
+ await supabase
+ .from("team_roster")
+ .update({ left_at: new Date().toISOString() })
+ .eq("team_id", input.fromTeamId)
+ .eq("player_id", input.playerId)
+ .is("left_at", null);
+
+ const { error: rError } = await supabase.from("team_roster").insert({
+ team_id: input.toTeamId,
+ player_id: input.playerId,
+ competition_id: input.competitionId,
+ });
+ if (rError) throw new Error(rError.message);
+}
+
+export async function listTransfers(
+ supabase: SupabaseClient,
+ competitionId: string
+) {
+ const { data, error } = await supabase
+ .from("transfers")
+ .select(
+ `*, player:players(display_name), from_team:from_team_id(name), to_team:to_team_id(name)`
+ )
+ .eq("competition_id", competitionId)
+ .order("created_at", { ascending: false })
+ .limit(50);
+ if (error) throw new Error(error.message);
+ return data;
+}
diff --git a/lib/services/teams.ts b/lib/services/teams.ts
new file mode 100644
index 0000000..410688e
--- /dev/null
+++ b/lib/services/teams.ts
@@ -0,0 +1,125 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+
+export async function createTeam(
+ supabase: SupabaseClient,
+ competitionId: string,
+ input: { name: string; nickname?: string; icon?: string }
+) {
+ const { data, error } = await supabase
+ .from("teams")
+ .insert({
+ competition_id: competitionId,
+ name: input.name,
+ nickname: input.nickname || null,
+ icon: input.icon || "shield",
+ })
+ .select()
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function deleteTeam(supabase: SupabaseClient, teamId: string) {
+ const { error } = await supabase.from("teams").delete().eq("id", teamId);
+ if (error) throw new Error(error.message);
+}
+
+export async function listTeams(
+ supabase: SupabaseClient,
+ competitionId: string
+) {
+ const { data, error } = await supabase
+ .from("teams")
+ .select("*")
+ .eq("competition_id", competitionId)
+ .order("name");
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function updateTeam(
+ supabase: SupabaseClient,
+ teamId: string,
+ updates: {
+ home_stadium_name?: string;
+ logo_path?: string;
+ nickname?: string;
+ icon?: string;
+ }
+) {
+ const { data, error } = await supabase
+ .from("teams")
+ .update(updates)
+ .eq("id", teamId)
+ .select()
+ .single();
+ if (error) throw new Error(error.message);
+ return data;
+}
+
+export async function setAvailability(
+ supabase: SupabaseClient,
+ teamId: string,
+ windows: { day_of_week: number; start_time?: string; end_time?: string }[]
+) {
+ await supabase.from("team_availability").delete().eq("team_id", teamId);
+ if (windows.length === 0) return;
+ const { error } = await supabase.from("team_availability").insert(
+ windows.map((w) => ({
+ team_id: teamId,
+ day_of_week: w.day_of_week,
+ start_time: w.start_time || null,
+ end_time: w.end_time || null,
+ }))
+ );
+ if (error) throw new Error(error.message);
+}
+
+export async function getManagerTeam(
+ supabase: SupabaseClient,
+ userId: string,
+ competitionId: string
+) {
+ const { data: teams } = await supabase
+ .from("teams")
+ .select("id")
+ .eq("competition_id", competitionId);
+ const teamIds = teams?.map((t) => t.id) ?? [];
+ if (teamIds.length === 0) return null;
+
+ const { data } = await supabase
+ .from("team_members")
+ .select("team_id, teams(*)")
+ .eq("user_id", userId)
+ .eq("role", "manager")
+ .in("team_id", teamIds)
+ .limit(1)
+ .maybeSingle();
+
+ return data;
+}
+
+export async function getTeamDashboard(
+ supabase: SupabaseClient,
+ teamId: string,
+ competitionId: string
+) {
+ const [results, playerStats] = await Promise.all([
+ supabase
+ .from("team_match_results")
+ .select("*")
+ .eq("team_id", teamId)
+ .order("matchday", { ascending: true }),
+ supabase
+ .from("player_competition_stats")
+ .select("*")
+ .eq("team_id", teamId)
+ .eq("competition_id", competitionId)
+ .order("goals", { ascending: false }),
+ ]);
+
+ return {
+ results: results.data ?? [],
+ playerStats: playerStats.data ?? [],
+ };
+}
diff --git a/lib/supabase/admin.ts b/lib/supabase/admin.ts
new file mode 100644
index 0000000..290950e
--- /dev/null
+++ b/lib/supabase/admin.ts
@@ -0,0 +1,18 @@
+import { createClient } from "@supabase/supabase-js";
+import { getSupabaseEnv } from "./env";
+
+/** Server-only Supabase client (service role). Never import in client components. */
+export function createAdminClient() {
+ const { url } = getSupabaseEnv();
+ const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY?.trim();
+ if (!serviceKey) {
+ throw new Error("SUPABASE_SERVICE_ROLE_KEY is not set");
+ }
+ return createClient(url, serviceKey, {
+ auth: { autoRefreshToken: false, persistSession: false },
+ });
+}
+
+export function hasAdminClient(): boolean {
+ return Boolean(process.env.SUPABASE_SERVICE_ROLE_KEY?.trim());
+}
diff --git a/lib/supabase/auth-errors.ts b/lib/supabase/auth-errors.ts
new file mode 100644
index 0000000..111fef9
--- /dev/null
+++ b/lib/supabase/auth-errors.ts
@@ -0,0 +1,59 @@
+/** User-facing messages for Supabase Auth API errors. */
+
+type AuthLikeError = {
+ message?: string;
+ status?: number;
+ code?: string;
+};
+
+export function isAuthRateLimitError(error: AuthLikeError | null | undefined): boolean {
+ if (!error) return false;
+ if (error.status === 429) return true;
+ const msg = (error.message ?? "").toLowerCase();
+ return (
+ msg.includes("rate limit") ||
+ msg.includes("too many requests") ||
+ msg.includes("email rate limit")
+ );
+}
+
+export function formatSignupError(message: string): string {
+ const lower = message.toLowerCase();
+ if (
+ lower.includes("database error saving new user") ||
+ lower.includes("unexpected_failure")
+ ) {
+ return [
+ "Account could not be saved in the database (profile setup failed).",
+ "",
+ "Fix:",
+ "1. Run: npm run db:push",
+ "2. Or run supabase/migrations/20250524000008_fix_signup_trigger.sql in the SQL Editor",
+ "3. Try signup again",
+ ].join("\n");
+ }
+ if (lower.includes("user already registered")) {
+ return "This email is already registered. Try signing in or use Forgot password.";
+ }
+ return message;
+}
+
+export function formatAuthError(error: AuthLikeError | null | undefined): string {
+ if (!error) return "Something went wrong. Please try again.";
+
+ if (isAuthRateLimitError(error)) {
+ return [
+ "Too many password-reset emails were sent recently.",
+ "",
+ "Supabase limits auth emails (especially on the free plan — often about 2 per hour per project).",
+ "",
+ "What to do:",
+ "• Wait 60 minutes, then try once (do not spam the button).",
+ "• Check inbox and spam for an email you already received — the link may still work.",
+ "• Or reset from the dashboard: Authentication → Users → your user → Send password recovery.",
+ "• For local dev: npm run auth:reset-password -- email@example.com NewPassword",
+ ].join("\n");
+ }
+
+ return formatSignupError(error.message ?? "Something went wrong. Please try again.");
+}
diff --git a/lib/supabase/client.ts b/lib/supabase/client.ts
new file mode 100644
index 0000000..3e12333
--- /dev/null
+++ b/lib/supabase/client.ts
@@ -0,0 +1,7 @@
+import { createBrowserClient } from "@supabase/ssr";
+import { getSupabaseEnv } from "./env";
+
+export function createClient() {
+ const { url, anonKey } = getSupabaseEnv();
+ return createBrowserClient(url, anonKey);
+}
diff --git a/lib/supabase/env.ts b/lib/supabase/env.ts
new file mode 100644
index 0000000..010090f
--- /dev/null
+++ b/lib/supabase/env.ts
@@ -0,0 +1,59 @@
+/** Trim values — .env files edited on Windows often include stray \\r */
+function clean(value: string | undefined): string | undefined {
+ return value?.trim().replace(/\r$/, "").replace(/\n$/, "");
+}
+
+export function getSupabaseEnv() {
+ const url = clean(process.env.NEXT_PUBLIC_SUPABASE_URL);
+ const anonKey = clean(
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ??
+ process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
+ );
+
+ if (!url) {
+ throw new Error(
+ "Missing NEXT_PUBLIC_SUPABASE_URL in .env.local — restart dev server after editing."
+ );
+ }
+ if (url.includes("your-project") || url.includes("YOUR_REF")) {
+ throw new Error(
+ "NEXT_PUBLIC_SUPABASE_URL is still the placeholder. Set your real URL in .env.local (e.g. https://vcxpcyafnlyiyqmapyyy.supabase.co) and restart npm run dev."
+ );
+ }
+ if (!url.startsWith("https://") || !url.includes(".supabase.co")) {
+ throw new Error(
+ "NEXT_PUBLIC_SUPABASE_URL should look like https://YOUR_REF.supabase.co"
+ );
+ }
+ if (!anonKey) {
+ throw new Error(
+ "Missing NEXT_PUBLIC_SUPABASE_ANON_KEY in .env.local — use the anon or publishable key from Dashboard → API."
+ );
+ }
+
+ return { url, anonKey };
+}
+
+export function formatAuthNetworkError(cause: unknown): string {
+ if (cause instanceof Error && cause.message.includes("NEXT_PUBLIC")) {
+ return cause.message;
+ }
+ const msg = cause instanceof Error ? cause.message : String(cause);
+ if (msg === "Failed to fetch" || msg.includes("NetworkError")) {
+ return [
+ "Cannot reach Supabase (network error).",
+ "• Confirm project is active in the Supabase dashboard",
+ "• Use the full API key from Dashboard → API (try the legacy anon key starting with eyJ… if publishable key fails)",
+ "• Restart: npm run dev after changing .env.local",
+ "• Add http://localhost:3000 to Auth → URL configuration → Redirect URLs",
+ ].join("\n");
+ }
+ if (msg.includes("429") || /rate limit/i.test(msg)) {
+ return [
+ "Too many requests to Supabase Auth (rate limited).",
+ "Wait about 60 minutes before trying password reset again.",
+ "See docs/PASSWORD_RESET.md for dashboard and dev workarounds.",
+ ].join("\n");
+ }
+ return msg || "Something went wrong. Please try again.";
+}
diff --git a/lib/supabase/middleware.ts b/lib/supabase/middleware.ts
new file mode 100644
index 0000000..aa7e6f4
--- /dev/null
+++ b/lib/supabase/middleware.ts
@@ -0,0 +1,111 @@
+import { createServerClient } from "@supabase/ssr";
+import { NextResponse, type NextRequest } from "next/server";
+import { getSupabaseEnv } from "./env";
+import {
+ loginForPath,
+ pathForRole,
+ roleForPath,
+} from "@/lib/middleware/portal";
+import type { PortalRole } from "@/lib/auth/roles";
+import { portalRoleFromMetadata } from "@/lib/auth/resolve-portal-role";
+
+export async function updateSession(request: NextRequest) {
+ let supabaseResponse = NextResponse.next({ request });
+
+ let url: string;
+ let anonKey: string;
+ try {
+ ({ url, anonKey } = getSupabaseEnv());
+ } catch {
+ return supabaseResponse;
+ }
+
+ const supabase = createServerClient(url, anonKey, {
+ cookies: {
+ getAll() {
+ return request.cookies.getAll();
+ },
+ setAll(cookiesToSet) {
+ cookiesToSet.forEach(({ name, value }) =>
+ request.cookies.set(name, value)
+ );
+ supabaseResponse = NextResponse.next({ request });
+ cookiesToSet.forEach(({ name, value, options }) =>
+ supabaseResponse.cookies.set(name, value, options)
+ );
+ },
+ },
+ });
+
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+
+ const pathname = request.nextUrl.pathname;
+ const isAuthPage =
+ pathname.startsWith("/login") || pathname.startsWith("/signup");
+ const isPasswordFlow =
+ pathname.startsWith("/forgot-password") ||
+ pathname === "/reset-password" ||
+ pathname.startsWith("/auth/");
+ const isApi = pathname.startsWith("/api/");
+ const isApiHealth = pathname === "/api/health";
+ const isPublic =
+ pathname === "/" || isAuthPage || isApiHealth || isPasswordFlow;
+ const requiredRole = roleForPath(pathname);
+
+ if (!user && !isPublic && !isApi) {
+ const redirectUrl = request.nextUrl.clone();
+ redirectUrl.pathname = loginForPath(pathname);
+ return NextResponse.redirect(redirectUrl);
+ }
+
+ let portalRole: PortalRole | null = null;
+ if (user) {
+ const { data: profile, error: profileError } = await supabase
+ .from("profiles")
+ .select("portal_role")
+ .eq("id", user.id)
+ .maybeSingle();
+
+ if (!profileError && profile?.portal_role) {
+ portalRole = profile.portal_role as PortalRole;
+ } else {
+ portalRole = portalRoleFromMetadata(user) ?? "manager";
+ }
+ }
+
+ if (user && isAuthPage && !isPasswordFlow) {
+ const redirectUrl = request.nextUrl.clone();
+ redirectUrl.pathname = pathForRole(portalRole);
+ return NextResponse.redirect(redirectUrl);
+ }
+
+ if (user && pathname === "/reset-password") {
+ return supabaseResponse;
+ }
+
+ if (user && requiredRole && portalRole !== requiredRole) {
+ const redirectUrl = request.nextUrl.clone();
+ redirectUrl.pathname = pathForRole(portalRole);
+ return NextResponse.redirect(redirectUrl);
+ }
+
+ if (user && pathname === "/players" && portalRole === "manager") {
+ const redirectUrl = request.nextUrl.clone();
+ redirectUrl.pathname = pathForRole(portalRole);
+ return NextResponse.redirect(redirectUrl);
+ }
+
+ if (user && pathname === "/leagues" && portalRole === "manager") {
+ const redirectUrl = request.nextUrl.clone();
+ redirectUrl.pathname = "/manager/leagues";
+ return NextResponse.redirect(redirectUrl);
+ }
+
+ if (user && pathname.startsWith("/leagues/") && portalRole === "manager") {
+ return supabaseResponse;
+ }
+
+ return supabaseResponse;
+}
diff --git a/lib/supabase/server.ts b/lib/supabase/server.ts
new file mode 100644
index 0000000..d89e8fe
--- /dev/null
+++ b/lib/supabase/server.ts
@@ -0,0 +1,25 @@
+import { createServerClient } from "@supabase/ssr";
+import { cookies } from "next/headers";
+import { getSupabaseEnv } from "./env";
+
+export async function createClient() {
+ const { url, anonKey } = getSupabaseEnv();
+ const cookieStore = await cookies();
+
+ return createServerClient(url, anonKey, {
+ cookies: {
+ getAll() {
+ return cookieStore.getAll();
+ },
+ setAll(cookiesToSet) {
+ try {
+ cookiesToSet.forEach(({ name, value, options }) =>
+ cookieStore.set(name, value, options)
+ );
+ } catch {
+ // Server Component — ignore
+ }
+ },
+ },
+ });
+}
diff --git a/lib/utils.ts b/lib/utils.ts
new file mode 100644
index 0000000..52c8cef
--- /dev/null
+++ b/lib/utils.ts
@@ -0,0 +1,24 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+
+export function slugify(text: string): string {
+ return text
+ .toLowerCase()
+ .trim()
+ .replace(/[^\w\s-]/g, "")
+ .replace(/[\s_-]+/g, "-")
+ .replace(/^-+|-+$/g, "");
+}
+
+export function getTeamLogoUrl(logoPath: string | null | undefined): string | null {
+ if (!logoPath) return null;
+ const base = process.env.NEXT_PUBLIC_SUPABASE_URL;
+ if (!base) return null;
+ return `${base}/storage/v1/object/public/team-logos/${logoPath}`;
+}
+
+export const DAY_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
diff --git a/middleware.ts b/middleware.ts
new file mode 100644
index 0000000..20d59ff
--- /dev/null
+++ b/middleware.ts
@@ -0,0 +1,12 @@
+import { type NextRequest } from "next/server";
+import { updateSession } from "@/lib/supabase/middleware";
+
+export async function middleware(request: NextRequest) {
+ return await updateSession(request);
+}
+
+export const config = {
+ matcher: [
+ "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
+ ],
+};
diff --git a/next.config.ts b/next.config.ts
new file mode 100644
index 0000000..5a781d5
--- /dev/null
+++ b/next.config.ts
@@ -0,0 +1,24 @@
+import type { NextConfig } from "next";
+
+const nextConfig: NextConfig = {
+ images: {
+ remotePatterns: [
+ {
+ protocol: "https",
+ hostname: "*.supabase.co",
+ },
+ ],
+ },
+};
+
+export default nextConfig;
+
+try {
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
+ const { initOpenNextCloudflareForDev } = require("@opennextjs/cloudflare");
+ initOpenNextCloudflareForDev();
+} catch {
+ console.warn(
+ "[next.config] @opennextjs/cloudflare is not installed. Run: npm install"
+ );
+}
diff --git a/open-next.config.ts b/open-next.config.ts
new file mode 100644
index 0000000..183976d
--- /dev/null
+++ b/open-next.config.ts
@@ -0,0 +1,3 @@
+import { defineCloudflareConfig } from "@opennextjs/cloudflare";
+
+export default defineCloudflareConfig();
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..4932890
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,13420 @@
+{
+ "name": "yaltopia-fifa",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "yaltopia-fifa",
+ "version": "0.1.0",
+ "dependencies": {
+ "@opennextjs/cloudflare": "^1.6.0",
+ "@radix-ui/react-avatar": "^1.1.3",
+ "@radix-ui/react-dialog": "^1.1.6",
+ "@radix-ui/react-dropdown-menu": "^2.1.6",
+ "@radix-ui/react-label": "^2.1.2",
+ "@radix-ui/react-select": "^2.1.6",
+ "@radix-ui/react-slot": "^1.1.2",
+ "@radix-ui/react-tabs": "^1.1.3",
+ "@supabase/ssr": "^0.8.0",
+ "@supabase/supabase-js": "^2.86.0",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.475.0",
+ "next": "^15.2.0",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "recharts": "^2.15.1",
+ "tailwind-merge": "^3.0.1",
+ "zod": "^3.24.2"
+ },
+ "devDependencies": {
+ "@eslint/eslintrc": "^3.0.0",
+ "@tailwindcss/postcss": "^4.0.9",
+ "@types/node": "^22.0.0",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
+ "eslint": "^9.0.0",
+ "eslint-config-next": "^15.2.0",
+ "supabase": "^2.101.0",
+ "tailwindcss": "^4.0.9",
+ "typescript": "^5.0.0",
+ "wrangler": "^4.0.0"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ast-grep/napi": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi/-/napi-0.40.5.tgz",
+ "integrity": "sha512-hJA62OeBKUQT68DD2gDyhOqJxZxycqg8wLxbqjgqSzYttCMSDL9tiAQ9abgekBYNHudbJosm9sWOEbmCDfpX2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@ast-grep/napi-darwin-arm64": "0.40.5",
+ "@ast-grep/napi-darwin-x64": "0.40.5",
+ "@ast-grep/napi-linux-arm64-gnu": "0.40.5",
+ "@ast-grep/napi-linux-arm64-musl": "0.40.5",
+ "@ast-grep/napi-linux-x64-gnu": "0.40.5",
+ "@ast-grep/napi-linux-x64-musl": "0.40.5",
+ "@ast-grep/napi-win32-arm64-msvc": "0.40.5",
+ "@ast-grep/napi-win32-ia32-msvc": "0.40.5",
+ "@ast-grep/napi-win32-x64-msvc": "0.40.5"
+ }
+ },
+ "node_modules/@ast-grep/napi-darwin-arm64": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.40.5.tgz",
+ "integrity": "sha512-2F072fGN0WTq7KI3okuEnkGJVEHLbi56Bw1H6NAMf7j2mJJeQWsRyGOMcyNnUXZDeNdvoMH0OB2a5wwUegY/nQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-darwin-x64": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.40.5.tgz",
+ "integrity": "sha512-dJMidHZhhxuLBYNi6/FKI812jQ7wcFPSKkVPwviez2D+KvYagapUMAV/4dJ7FCORfguVk8Y0jpPAlYmWRT5nvA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-arm64-gnu": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.40.5.tgz",
+ "integrity": "sha512-nBRCbyoS87uqkaw4Oyfe5VO+SRm2B+0g0T8ME69Qry9ShMf41a2bTdpcQx9e8scZPogq+CTwDHo3THyBV71l9w==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-arm64-musl": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-musl/-/napi-linux-arm64-musl-0.40.5.tgz",
+ "integrity": "sha512-/qKsmds5FMoaEj6FdNzepbmLMtlFuBLdrAn9GIWCqOIcVcYvM1Nka8+mncfeXB/MFZKOrzQsQdPTWqrrQzXLrA==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-x64-gnu": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.40.5.tgz",
+ "integrity": "sha512-DP4oDbq7f/1A2hRTFLhJfDFR6aI5mRWdEfKfHzRItmlKsR9WlcEl1qDJs/zX9R2EEtIDsSKRzuJNfJllY3/W8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-linux-x64-musl": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.40.5.tgz",
+ "integrity": "sha512-BRZUvVBPUNpWPo6Ns8chXVzxHPY+k9gpsubGTHy92Q26ecZULd/dTkWWdnvfhRqttsSQ9Pe/XQdi5+hDQ6RYcg==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-win32-arm64-msvc": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.40.5.tgz",
+ "integrity": "sha512-y95zSEwc7vhxmcrcH0GnK4ZHEBQrmrszRBNQovzaciF9GUqEcCACNLoBesn4V47IaOp4fYgD2/EhGRTIBFb2Ug==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-win32-ia32-msvc": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.40.5.tgz",
+ "integrity": "sha512-K/u8De62iUnFCzVUs7FBdTZ2Jrgc5/DLHqjpup66KxZ7GIM9/HGME/O8aSoPkpcAeCD4TiTZ11C1i5p5H98hTg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ast-grep/napi-win32-x64-msvc": {
+ "version": "0.40.5",
+ "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.40.5.tgz",
+ "integrity": "sha512-dqm5zg/o4Nh4VOQPEpMS23ot8HVd22gG0eg01t4CFcZeuzyuSgBlOL3N7xLbz3iH2sVkk7keuBwAzOIpTqziNQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@aws-crypto/crc32": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
+ "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/crc32c": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz",
+ "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz",
+ "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/supports-web-crypto": "^5.2.0",
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
+ "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-js": "^5.2.0",
+ "@aws-crypto/supports-web-crypto": "^5.2.0",
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-js": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
+ "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/supports-web-crypto": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
+ "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
+ "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-cloudfront": {
+ "version": "3.984.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudfront/-/client-cloudfront-3.984.0.tgz",
+ "integrity": "sha512-couDuDLpJtoeWne/nYyJ+I+5ntBVdNgBVRTCoDaXuVV7OC3u/wz5Ps0+GogspEwMLEFoOJ8t691h3YXQtnpQTw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.6",
+ "@aws-sdk/credential-provider-node": "^3.972.5",
+ "@aws-sdk/middleware-host-header": "^3.972.3",
+ "@aws-sdk/middleware-logger": "^3.972.3",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.3",
+ "@aws-sdk/middleware-user-agent": "^3.972.6",
+ "@aws-sdk/region-config-resolver": "^3.972.3",
+ "@aws-sdk/types": "^3.973.1",
+ "@aws-sdk/util-endpoints": "3.984.0",
+ "@aws-sdk/util-user-agent-browser": "^3.972.3",
+ "@aws-sdk/util-user-agent-node": "^3.972.4",
+ "@smithy/config-resolver": "^4.4.6",
+ "@smithy/core": "^3.22.0",
+ "@smithy/fetch-http-handler": "^5.3.9",
+ "@smithy/hash-node": "^4.2.8",
+ "@smithy/invalid-dependency": "^4.2.8",
+ "@smithy/middleware-content-length": "^4.2.8",
+ "@smithy/middleware-endpoint": "^4.4.12",
+ "@smithy/middleware-retry": "^4.4.29",
+ "@smithy/middleware-serde": "^4.2.9",
+ "@smithy/middleware-stack": "^4.2.8",
+ "@smithy/node-config-provider": "^4.3.8",
+ "@smithy/node-http-handler": "^4.4.8",
+ "@smithy/protocol-http": "^5.3.8",
+ "@smithy/smithy-client": "^4.11.1",
+ "@smithy/types": "^4.12.0",
+ "@smithy/url-parser": "^4.2.8",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.28",
+ "@smithy/util-defaults-mode-node": "^4.2.31",
+ "@smithy/util-endpoints": "^3.2.8",
+ "@smithy/util-middleware": "^4.2.8",
+ "@smithy/util-retry": "^4.2.8",
+ "@smithy/util-stream": "^4.5.10",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/util-waiter": "^4.2.8",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb": {
+ "version": "3.984.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.984.0.tgz",
+ "integrity": "sha512-8/Oft9MWQtbG6p9f8eY5fsKC2CcO5YVDlwive8eUYS9mEbgnyQxm68OyH26WvsSTykQ9QkIbR+fOG56RsIBODw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.6",
+ "@aws-sdk/credential-provider-node": "^3.972.5",
+ "@aws-sdk/dynamodb-codec": "^3.972.7",
+ "@aws-sdk/middleware-endpoint-discovery": "^3.972.3",
+ "@aws-sdk/middleware-host-header": "^3.972.3",
+ "@aws-sdk/middleware-logger": "^3.972.3",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.3",
+ "@aws-sdk/middleware-user-agent": "^3.972.6",
+ "@aws-sdk/region-config-resolver": "^3.972.3",
+ "@aws-sdk/types": "^3.973.1",
+ "@aws-sdk/util-endpoints": "3.984.0",
+ "@aws-sdk/util-user-agent-browser": "^3.972.3",
+ "@aws-sdk/util-user-agent-node": "^3.972.4",
+ "@smithy/config-resolver": "^4.4.6",
+ "@smithy/core": "^3.22.0",
+ "@smithy/fetch-http-handler": "^5.3.9",
+ "@smithy/hash-node": "^4.2.8",
+ "@smithy/invalid-dependency": "^4.2.8",
+ "@smithy/middleware-content-length": "^4.2.8",
+ "@smithy/middleware-endpoint": "^4.4.12",
+ "@smithy/middleware-retry": "^4.4.29",
+ "@smithy/middleware-serde": "^4.2.9",
+ "@smithy/middleware-stack": "^4.2.8",
+ "@smithy/node-config-provider": "^4.3.8",
+ "@smithy/node-http-handler": "^4.4.8",
+ "@smithy/protocol-http": "^5.3.8",
+ "@smithy/smithy-client": "^4.11.1",
+ "@smithy/types": "^4.12.0",
+ "@smithy/url-parser": "^4.2.8",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.28",
+ "@smithy/util-defaults-mode-node": "^4.2.31",
+ "@smithy/util-endpoints": "^3.2.8",
+ "@smithy/util-middleware": "^4.2.8",
+ "@smithy/util-retry": "^4.2.8",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/util-waiter": "^4.2.8",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-lambda": {
+ "version": "3.984.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.984.0.tgz",
+ "integrity": "sha512-kqwNBIGNxGVhINwgN/UQfdsQkaMjbu9PFV2EhATWouV+RT60uMjK9JENgLDwbgJmEVbbnPsh9HaZ5KKwPSdiDg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.6",
+ "@aws-sdk/credential-provider-node": "^3.972.5",
+ "@aws-sdk/middleware-host-header": "^3.972.3",
+ "@aws-sdk/middleware-logger": "^3.972.3",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.3",
+ "@aws-sdk/middleware-user-agent": "^3.972.6",
+ "@aws-sdk/region-config-resolver": "^3.972.3",
+ "@aws-sdk/types": "^3.973.1",
+ "@aws-sdk/util-endpoints": "3.984.0",
+ "@aws-sdk/util-user-agent-browser": "^3.972.3",
+ "@aws-sdk/util-user-agent-node": "^3.972.4",
+ "@smithy/config-resolver": "^4.4.6",
+ "@smithy/core": "^3.22.0",
+ "@smithy/eventstream-serde-browser": "^4.2.8",
+ "@smithy/eventstream-serde-config-resolver": "^4.3.8",
+ "@smithy/eventstream-serde-node": "^4.2.8",
+ "@smithy/fetch-http-handler": "^5.3.9",
+ "@smithy/hash-node": "^4.2.8",
+ "@smithy/invalid-dependency": "^4.2.8",
+ "@smithy/middleware-content-length": "^4.2.8",
+ "@smithy/middleware-endpoint": "^4.4.12",
+ "@smithy/middleware-retry": "^4.4.29",
+ "@smithy/middleware-serde": "^4.2.9",
+ "@smithy/middleware-stack": "^4.2.8",
+ "@smithy/node-config-provider": "^4.3.8",
+ "@smithy/node-http-handler": "^4.4.8",
+ "@smithy/protocol-http": "^5.3.8",
+ "@smithy/smithy-client": "^4.11.1",
+ "@smithy/types": "^4.12.0",
+ "@smithy/url-parser": "^4.2.8",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.28",
+ "@smithy/util-defaults-mode-node": "^4.2.31",
+ "@smithy/util-endpoints": "^3.2.8",
+ "@smithy/util-middleware": "^4.2.8",
+ "@smithy/util-retry": "^4.2.8",
+ "@smithy/util-stream": "^4.5.10",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/util-waiter": "^4.2.8",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3": {
+ "version": "3.984.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.984.0.tgz",
+ "integrity": "sha512-7ny2Slr93Y+QniuluvcfWwyDi32zWQfznynL56Tk0vVh7bWrvS/odm8WP2nInKicRVNipcJHY2YInur6Q/9V0A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha1-browser": "5.2.0",
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.6",
+ "@aws-sdk/credential-provider-node": "^3.972.5",
+ "@aws-sdk/middleware-bucket-endpoint": "^3.972.3",
+ "@aws-sdk/middleware-expect-continue": "^3.972.3",
+ "@aws-sdk/middleware-flexible-checksums": "^3.972.4",
+ "@aws-sdk/middleware-host-header": "^3.972.3",
+ "@aws-sdk/middleware-location-constraint": "^3.972.3",
+ "@aws-sdk/middleware-logger": "^3.972.3",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.3",
+ "@aws-sdk/middleware-sdk-s3": "^3.972.6",
+ "@aws-sdk/middleware-ssec": "^3.972.3",
+ "@aws-sdk/middleware-user-agent": "^3.972.6",
+ "@aws-sdk/region-config-resolver": "^3.972.3",
+ "@aws-sdk/signature-v4-multi-region": "3.984.0",
+ "@aws-sdk/types": "^3.973.1",
+ "@aws-sdk/util-endpoints": "3.984.0",
+ "@aws-sdk/util-user-agent-browser": "^3.972.3",
+ "@aws-sdk/util-user-agent-node": "^3.972.4",
+ "@smithy/config-resolver": "^4.4.6",
+ "@smithy/core": "^3.22.0",
+ "@smithy/eventstream-serde-browser": "^4.2.8",
+ "@smithy/eventstream-serde-config-resolver": "^4.3.8",
+ "@smithy/eventstream-serde-node": "^4.2.8",
+ "@smithy/fetch-http-handler": "^5.3.9",
+ "@smithy/hash-blob-browser": "^4.2.9",
+ "@smithy/hash-node": "^4.2.8",
+ "@smithy/hash-stream-node": "^4.2.8",
+ "@smithy/invalid-dependency": "^4.2.8",
+ "@smithy/md5-js": "^4.2.8",
+ "@smithy/middleware-content-length": "^4.2.8",
+ "@smithy/middleware-endpoint": "^4.4.12",
+ "@smithy/middleware-retry": "^4.4.29",
+ "@smithy/middleware-serde": "^4.2.9",
+ "@smithy/middleware-stack": "^4.2.8",
+ "@smithy/node-config-provider": "^4.3.8",
+ "@smithy/node-http-handler": "^4.4.8",
+ "@smithy/protocol-http": "^5.3.8",
+ "@smithy/smithy-client": "^4.11.1",
+ "@smithy/types": "^4.12.0",
+ "@smithy/url-parser": "^4.2.8",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.28",
+ "@smithy/util-defaults-mode-node": "^4.2.31",
+ "@smithy/util-endpoints": "^3.2.8",
+ "@smithy/util-middleware": "^4.2.8",
+ "@smithy/util-retry": "^4.2.8",
+ "@smithy/util-stream": "^4.5.10",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/util-waiter": "^4.2.8",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sqs": {
+ "version": "3.984.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.984.0.tgz",
+ "integrity": "sha512-TDvHpOUWlpanc3xQ5Xw0y8L2hoojBFCCSmXQ/6rKqGOf1ScX3dMA+K9aF0Zp0iwjhSh4VvsHD42esl8XwQZDjA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.6",
+ "@aws-sdk/credential-provider-node": "^3.972.5",
+ "@aws-sdk/middleware-host-header": "^3.972.3",
+ "@aws-sdk/middleware-logger": "^3.972.3",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.3",
+ "@aws-sdk/middleware-sdk-sqs": "^3.972.5",
+ "@aws-sdk/middleware-user-agent": "^3.972.6",
+ "@aws-sdk/region-config-resolver": "^3.972.3",
+ "@aws-sdk/types": "^3.973.1",
+ "@aws-sdk/util-endpoints": "3.984.0",
+ "@aws-sdk/util-user-agent-browser": "^3.972.3",
+ "@aws-sdk/util-user-agent-node": "^3.972.4",
+ "@smithy/config-resolver": "^4.4.6",
+ "@smithy/core": "^3.22.0",
+ "@smithy/fetch-http-handler": "^5.3.9",
+ "@smithy/hash-node": "^4.2.8",
+ "@smithy/invalid-dependency": "^4.2.8",
+ "@smithy/md5-js": "^4.2.8",
+ "@smithy/middleware-content-length": "^4.2.8",
+ "@smithy/middleware-endpoint": "^4.4.12",
+ "@smithy/middleware-retry": "^4.4.29",
+ "@smithy/middleware-serde": "^4.2.9",
+ "@smithy/middleware-stack": "^4.2.8",
+ "@smithy/node-config-provider": "^4.3.8",
+ "@smithy/node-http-handler": "^4.4.8",
+ "@smithy/protocol-http": "^5.3.8",
+ "@smithy/smithy-client": "^4.11.1",
+ "@smithy/types": "^4.12.0",
+ "@smithy/url-parser": "^4.2.8",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.28",
+ "@smithy/util-defaults-mode-node": "^4.2.31",
+ "@smithy/util-endpoints": "^3.2.8",
+ "@smithy/util-middleware": "^4.2.8",
+ "@smithy/util-retry": "^4.2.8",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/core": {
+ "version": "3.974.13",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.974.13.tgz",
+ "integrity": "sha512-+Y5/4tHki0uYgyx8eun146DegRVQBpdKGK5RbV0FTKJPpaKTchvqVxrrRFK6Wk0JksO4iAZKw3eqxGEIwtO98w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.9",
+ "@aws-sdk/xml-builder": "^3.972.25",
+ "@aws/lambda-invoke-store": "^0.2.2",
+ "@smithy/core": "^3.24.3",
+ "@smithy/signature-v4": "^5.4.2",
+ "@smithy/types": "^4.14.2",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/crc64-nvme": {
+ "version": "3.972.9",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/crc64-nvme/-/crc64-nvme-3.972.9.tgz",
+ "integrity": "sha512-P+QGozmXn2mZZI7sDgk+aUm+RTI61MPSFB+Ir2vjEjEbEsE4e7hYtzrDvAUxZy9ko81h53e11+F/GYlvwDkaOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.972.39",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.39.tgz",
+ "integrity": "sha512-29wX9zpAvEt1vcj0psha+y6ygBHy2V/S72mp6e7q0KARLWXq+pwE/lR6qGkwknQvruh52lXvlqZIga8Hdxkucw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.972.41",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.41.tgz",
+ "integrity": "sha512-IA3CQTjtJkb6u1H4mE4936c8OPBMa9Jggtwe8U2Mqw/vvb/tZ5Ebd0mcZcX0uKWQhOyYo/+qNIwkV5Xh+FeJJA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/fetch-http-handler": "^5.4.3",
+ "@smithy/node-http-handler": "^4.7.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.972.43",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.43.tgz",
+ "integrity": "sha512-4mzII+3mZEVXXE1xzrLQrCJL7/r62A63bA6SVzZoNL5rqCJghpf+xgGltVrIBBs0n+mOZBKrQl2tRREtvZ5l6A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/credential-provider-env": "^3.972.39",
+ "@aws-sdk/credential-provider-http": "^3.972.41",
+ "@aws-sdk/credential-provider-login": "^3.972.43",
+ "@aws-sdk/credential-provider-process": "^3.972.39",
+ "@aws-sdk/credential-provider-sso": "^3.972.43",
+ "@aws-sdk/credential-provider-web-identity": "^3.972.43",
+ "@aws-sdk/nested-clients": "^3.997.11",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/credential-provider-imds": "^4.3.2",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login": {
+ "version": "3.972.43",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.43.tgz",
+ "integrity": "sha512-HG7kQCwXtbv3oBV61Ins0oNX8KKyvrMqqRkb6ZiAfQHbMuHaiNaEb2KnpKLPkNpqImSBK82UkVE/kaY6IfWikA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/nested-clients": "^3.997.11",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.972.44",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.44.tgz",
+ "integrity": "sha512-sDaBIT0yrNNIPfvlsiTCmANm07zKju+ipWODjEXgZlsjMeIJR3LVp7RDyAOzUoAsTbDfYKDWp+i5WrFiQP6rmQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "^3.972.39",
+ "@aws-sdk/credential-provider-http": "^3.972.41",
+ "@aws-sdk/credential-provider-ini": "^3.972.43",
+ "@aws-sdk/credential-provider-process": "^3.972.39",
+ "@aws-sdk/credential-provider-sso": "^3.972.43",
+ "@aws-sdk/credential-provider-web-identity": "^3.972.43",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/credential-provider-imds": "^4.3.2",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.972.39",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.39.tgz",
+ "integrity": "sha512-2k/amBifLd75eXNwgvPw/2lKYSQ3NhvHQgkVKVjfUq13/eJ3JRtHmznuFenn74OK3sSfp4SMy1YB2w+UVXoKqA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.972.43",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.43.tgz",
+ "integrity": "sha512-LPc3+Y4vhH1T4x6CMqwCM6hk5+SRf/Lwmgm8INm95wxTtIRHcMwQUVkDzWu4Iw/RSncxYM2BC01OrYbxOPZvyg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/nested-clients": "^3.997.11",
+ "@aws-sdk/token-providers": "3.1052.0",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.972.43",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.43.tgz",
+ "integrity": "sha512-wQtL34lUD/09VXjwAUo2T+I3aEXRDxMB3DKmTJL/Zj0Gi6sLDTrVhae1XVt01yzkquOWajI/sZW72JGDZ1ciTw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/nested-clients": "^3.997.11",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/dynamodb-codec": {
+ "version": "3.973.13",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.973.13.tgz",
+ "integrity": "sha512-UPiKWOcjAZcj5/t6l8vxcfkPCDubTKvwtx6yvZeylEg1nMlIi7QzGnuJkf+WFumQmAaN/6GtBjA84gLvdFr5XA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/endpoint-cache": {
+ "version": "3.972.5",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.972.5.tgz",
+ "integrity": "sha512-itVdge0NozgtgmtbZ25FVwWU3vGlE7x7feE/aOEJNkQfEpbkrF8Rj1QmnK+2blFfYE1xWt/iU+6/jUp/pv1+MA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "mnemonist": "0.38.3",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint": {
+ "version": "3.972.15",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.972.15.tgz",
+ "integrity": "sha512-O2HDANa+MrvbxpaRVQDiH3T13uAa9AkMjKyZmDygwauAmmvqZ5B0iRmKW+fuVGW6NPXuyXurFgIx69lSvmAWGA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-endpoint-discovery": {
+ "version": "3.972.14",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.972.14.tgz",
+ "integrity": "sha512-wRIopAjPr4hUT1SnaM+pf4A3M90NjGDEMnmDf/rRN2P99sPRB/fnxllIVJcfAIwvFdK8nQLllYZt6V6k/5maBQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/endpoint-cache": "^3.972.5",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue": {
+ "version": "3.972.13",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.972.13.tgz",
+ "integrity": "sha512-sHiqIFg8o2ipT7t40B89Vj0ubSUtY6OSt/+Ee/OXhHch5K4+81zP2+QX8Lkc/nJ2QSmCySxOke7TEbmX69fe2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums": {
+ "version": "3.974.21",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.21.tgz",
+ "integrity": "sha512-alAu9heyiBK/OmRNXVxq8mmPTgeW2AQ6EYjRsI38kPZa1MZvt2Jh+BlGq7/GG9OVXOaEgD7DlGj/Lzfy5OmuEg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@aws-crypto/crc32c": "5.2.0",
+ "@aws-crypto/util": "5.2.0",
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/crc64-nvme": "^3.972.9",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.972.14",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.14.tgz",
+ "integrity": "sha512-Q1wVLhOwOiifMJt12IK/reHZpGERbeom8QirjX4JxfxYYqhSjBR50JSZAXhrheI1pSYkL5wLGXJLUMJLdyS75g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-location-constraint": {
+ "version": "3.972.11",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.972.11.tgz",
+ "integrity": "sha512-hkfspNUP4criAH6ton6BGKgnm5dZx+7bUOy1YqlTfejDeUPAM23D81q/IX+hdlS3KUsfwGz5ADTqZWKBEUpf4A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.972.13",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.13.tgz",
+ "integrity": "sha512-uvoAP8dpzA2tAYek8fKaP9iGOYmrnZzWPlWAAs74gQdF0YbixpXE1ZOSClKq4PB5VADiVIIB43Vjc5rdOrw10A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.972.15",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.15.tgz",
+ "integrity": "sha512-VDMUHLeQ/yTr658HMm2eWS7e6qIFSxUeVbSA5zh4SNfSQ7ygIkJ0WeBoCnefw00Nsr5wNT8FIiAknJRTt058iw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-s3": {
+ "version": "3.972.42",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.42.tgz",
+ "integrity": "sha512-/xNqNGXv9LaxZd25L9VV4pnSOw9OdDNO4rAHamM+h3KQBSITljIH9vk3dveGga1I2j36lQd0rdG3gjNEXvtNew==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/signature-v4-multi-region": "^3.996.28",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/signature-v4": "^5.4.2",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.996.28",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.28.tgz",
+ "integrity": "sha512-qs9z5LqXO/CZC2Lg9SGKpoLU8Rhi+m2pFKZqfO9pytX1clc0katqtsDNupJxFy0xT9wsZSPzM2v1y+/H/zfp5Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/signature-v4": "^5.4.2",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-sqs": {
+ "version": "3.972.25",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.972.25.tgz",
+ "integrity": "sha512-xn/GUO23lRdeyDsOUvUpgzOMTKlHt0U4F2L0vCqUzyunKILoWuxspi36hfP7GinIrnIcudI4zLFD5+7fiIP3SA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-ssec": {
+ "version": "3.972.11",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.972.11.tgz",
+ "integrity": "sha512-7PQvGNhtveKlvVqNahqWx5yrwxP7ecwAoB1dYBf8eKwfo2tzzCbNnW+q2nO3N066ktQaB4iBQbDRWtizm+amoQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.972.43",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.43.tgz",
+ "integrity": "sha512-zXD7MSFgaxGi2CeURo9ZWKLNyXtfBUF0ByCHu4fdWa3WMu3YI8L0Mv3JHEDYBbYrUBPWBqSYhaXotxq0ADAGJg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients": {
+ "version": "3.997.11",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.11.tgz",
+ "integrity": "sha512-nWXXJ1r/r8N2Gw1pWolRgED38/A9A8DHR2ETWIv220zh4PZHcybbR4hUVWWktmNXTRHzDJwRluapHn0rZxuoqA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/signature-v4-multi-region": "^3.996.28",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/fetch-http-handler": "^5.4.3",
+ "@smithy/node-http-handler": "^4.7.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.996.28",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.28.tgz",
+ "integrity": "sha512-qs9z5LqXO/CZC2Lg9SGKpoLU8Rhi+m2pFKZqfO9pytX1clc0katqtsDNupJxFy0xT9wsZSPzM2v1y+/H/zfp5Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/signature-v4": "^5.4.2",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.972.17",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.17.tgz",
+ "integrity": "sha512-Jz0mg/eqfChGZm0G4bzm6CpyEEtu9ThG1WHY3uE/hGjIUIXPsyVyTuQOetUsrU9QiYWMknmyIKIEHpZ69BHzrA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.984.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.984.0.tgz",
+ "integrity": "sha512-TaWbfYCwnuOSvDSrgs7QgoaoXse49E7LzUkVOUhoezwB7bkmhp+iojADm7UepCEu4021SquD7NG1xA+WCvmldA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-sdk-s3": "^3.972.6",
+ "@aws-sdk/types": "^3.973.1",
+ "@smithy/protocol-http": "^5.3.8",
+ "@smithy/signature-v4": "^5.3.8",
+ "@smithy/types": "^4.12.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers": {
+ "version": "3.1052.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1052.0.tgz",
+ "integrity": "sha512-QqZNB3so7UIDxZtroc85TQaLVxdZRFm0eWM1CSR2N+b06as9TOrilvrlTZuj3guYlxMs6yLOgGxnklJ5qMYtTw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "@aws-sdk/nested-clients": "^3.997.11",
+ "@aws-sdk/types": "^3.973.9",
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/types": {
+ "version": "3.973.9",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.9.tgz",
+ "integrity": "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.984.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.984.0.tgz",
+ "integrity": "sha512-9ebjLA0hMKHeVvXEtTDCCOBtwjb0bOXiuUV06HNeVdgAjH6gj4x4Zwt4IBti83TiyTGOCl5YfZqGx4ehVsasbQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.1",
+ "@smithy/types": "^4.12.0",
+ "@smithy/url-parser": "^4.2.8",
+ "@smithy/util-endpoints": "^3.2.8",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-locate-window": {
+ "version": "3.965.5",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz",
+ "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.972.14",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.14.tgz",
+ "integrity": "sha512-LiMxdKWw55ZJP4iABqeIuF3RPgWMa2Uc9ZXjZRXZywStvH1IlzU6t+dKzcjS5ZQpHsl2A0G8UXxuy1zDY93YTQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.973.29",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.29.tgz",
+ "integrity": "sha512-sVUv711QtRMT8NYql9elQaAKCz8qopg+Y2Vf5ROLXeOqEWdYZp2g+9HBesTmLn48jDvI0i1khxPFKSwCjWaawA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/xml-builder": {
+ "version": "3.972.25",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.25.tgz",
+ "integrity": "sha512-GH+Kjz4nPKWKHnsiQpnhP1MJdTGIcK4rAka6tzakgjjUkVgNsmPeEbbRAf09SzS1hjGu6duGHCBsxYke0BhHjQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@nodable/entities": "2.1.0",
+ "@smithy/types": "^4.14.2",
+ "fast-xml-parser": "5.7.3",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws/lambda-invoke-store": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz",
+ "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.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/@cloudflare/kv-asset-handler": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz",
+ "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==",
+ "license": "MIT OR Apache-2.0",
+ "engines": {
+ "node": ">=22.0.0"
+ }
+ },
+ "node_modules/@cloudflare/unenv-preset": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz",
+ "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==",
+ "license": "MIT OR Apache-2.0",
+ "peerDependencies": {
+ "unenv": "2.0.0-rc.24",
+ "workerd": ">1.20260305.0 <2.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "workerd": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-64": {
+ "version": "1.20260521.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260521.1.tgz",
+ "integrity": "sha512-aiNdXmxlhwGjTSajL3I7uQPpN4lAOcXjvg5ZOlJKIywnevr798n9XCS6lvuqgniM3KjurBNWRRypMJntg/eSLg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-arm64": {
+ "version": "1.20260521.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260521.1.tgz",
+ "integrity": "sha512-ikN8aKSi4Ak28ndOkuSO5rq6lmV6wwDQu9F9Vu6J7EkwAOth74J/Hjn4j4EuFceW/npw2Ws0Y/muzA6WKHl4TA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-64": {
+ "version": "1.20260521.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260521.1.tgz",
+ "integrity": "sha512-D/gUhvQcG0pJr5aJl6yUoi2JxbFpjVtDq9xUJHPjfkAjL28TUVgCR/e5r8YGirepv4I1DK7ihuii9LZ2GGMJbw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-arm64": {
+ "version": "1.20260521.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260521.1.tgz",
+ "integrity": "sha512-vhjWPIHenczegTakhRPwEmTeaavCpNqsuo3RlLCkUdU47HrwLvy/4QersGggs4+kF4Do+IE/EznCGyT40xYcLA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-windows-64": {
+ "version": "1.20260521.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260521.1.tgz",
+ "integrity": "sha512-wBolYC/+lnGIEbkkPdzFtjTOWip2uQH6maeAP1ZV0kyxi5SGpsa83+wD5rH5OOle+sHE5qJMdwCKjwRwj+FKJg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx": {
+ "version": "1.31.0",
+ "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.31.0.tgz",
+ "integrity": "sha512-GeDxvtjiRuoyWVU9nQneId879zIyNdL05bS7RKiqMkfBSKpHMWHLoRyRqjYWLaXmX/llKO1hTlqHDmatkQAjPA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "commander": "^11.1.0",
+ "dotenv": "^16.4.5",
+ "eciesjs": "^0.4.10",
+ "execa": "^5.1.1",
+ "fdir": "^6.2.0",
+ "ignore": "^5.3.0",
+ "object-treeify": "1.1.33",
+ "picomatch": "^4.0.2",
+ "which": "^4.0.0"
+ },
+ "bin": {
+ "dotenvx": "src/cli/dotenvx.js",
+ "git-dotenvx": "src/cli/dotenvx.js"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/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/@dotenvx/dotenvx/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==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/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/@dotenvx/dotenvx/node_modules/which": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
+ "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^3.1.1"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@ecies/ciphers": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.6.tgz",
+ "integrity": "sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g==",
+ "license": "MIT",
+ "engines": {
+ "bun": ">=1",
+ "deno": ">=2.7.10",
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "@noble/ciphers": "^1.0.0"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.1",
+ "tslib": "^2.4.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/@emnapi/wasi-threads": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz",
+ "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz",
+ "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz",
+ "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz",
+ "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz",
+ "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz",
+ "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz",
+ "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz",
+ "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz",
+ "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz",
+ "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz",
+ "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz",
+ "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz",
+ "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz",
+ "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz",
+ "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz",
+ "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz",
+ "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz",
+ "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz",
+ "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz",
+ "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz",
+ "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
+ "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz",
+ "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz",
+ "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz",
+ "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz",
+ "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
+ "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.5"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
+ "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.14.0",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.5",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
+ "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "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/@humanfs/core": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
+ "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/types": "^0.15.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
+ "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.2",
+ "@humanfs/types": "^0.15.0",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/types": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
+ "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "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",
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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,
+ "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"
+ ],
+ "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"
+ ],
+ "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"
+ ],
+ "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==",
+ "dev": true,
+ "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/@napi-rs/wasm-runtime": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
+ "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tybys/wasm-util": "^0.10.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ },
+ "peerDependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.18.tgz",
+ "integrity": "sha512-hAV85Ckd9QR6RvH04MEKwsfLTksvFpO47j9xwtoIuvuPnlwecpSi+uZTtm8HirVbtlI2Fnz//xpcSTjFdyJk+g==",
+ "license": "MIT"
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.18.tgz",
+ "integrity": "sha512-w4MYq8M26a8PNrfto0JosLf5/3ssln1rsyP96g2DkC8uFVymStM5DLSz5ElxxrPRg2XnTMnFo3kREFlhYvxhWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-glob": "3.3.1"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.18.tgz",
+ "integrity": "sha512-w0WvQf1n+txiwns/9pwIQteCJpZTbxzO2SE0FLcwuD4v0WEh1JPOjdyxWL21XwJsdpx8cFRjyzxzCS/siP7HcQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.18.tgz",
+ "integrity": "sha512-znn71QmDuxm+BOaglihMZfvyySMnNljkVIY5Z2TCssBmm+WqL6c19VhtH5ktFkHa8EZ2bnTUpcNcmNSQsg67og==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.18.tgz",
+ "integrity": "sha512-yPPe5MNL+igZUa+OsqQJisqSfh6oarIuA1Q0BDxljGJhRQyZeP+WRHh7rs/jZUGMh5aY0YdIjXZG0VohkKkUdw==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.18.tgz",
+ "integrity": "sha512-glaCczEWIrHsokFZ3pP08U4BpKxwIdnT+txdOM32OBgpL9Yw4aqx8NejmgtZQZOdstQ5f0L3CasIZudzCuD+nw==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.18.tgz",
+ "integrity": "sha512-oUfg2EgJmU3R0OCOWiokGFUTvZiPfXtriXiuF3YNxRoROCdgvTedHIzYoeKH34gsZxS/V7mHbfq2hpAHwhH1/A==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.18.tgz",
+ "integrity": "sha512-JLxSP3KTd9iu/bvUMQxH7RJo9xKSHf55/6RPE4a6FTSZygGn7uvZbCej0AHXydwkggQGSD9UddSjwv6Xz5ESfA==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.18.tgz",
+ "integrity": "sha512-ir1v7enP52K2HNz3tQQvwF+x7VNxBk1ciiZ18WBPvxf4C59IqdfmHPJYK3vH7rSxpuCVw/8C712wTXNAtEp+NA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.18.tgz",
+ "integrity": "sha512-LIu5me6QTANCd25E7I5uIEfvgQ06RK7tvHAbYo3zCb3VpxQEPvMcSpd87NwUABDT6MbGPdEGR5VRiK4PPTJhQg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "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/curves": {
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
+ "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "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/@nodable/entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodable"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@node-minify/core": {
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/@node-minify/core/-/core-8.0.6.tgz",
+ "integrity": "sha512-/vxN46ieWDLU67CmgbArEvOb41zlYFOkOtr9QW9CnTrBLuTyGgkyNWC2y5+khvRw3Br58p2B5ZVSx/PxCTru6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@node-minify/utils": "8.0.6",
+ "glob": "9.3.5",
+ "mkdirp": "1.0.4"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@node-minify/core/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/@node-minify/core/node_modules/glob": {
+ "version": "9.3.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz",
+ "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "minimatch": "^8.0.2",
+ "minipass": "^4.2.4",
+ "path-scurry": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@node-minify/core/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@node-minify/core/node_modules/minimatch": {
+ "version": "8.0.7",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.7.tgz",
+ "integrity": "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@node-minify/core/node_modules/minipass": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz",
+ "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@node-minify/core/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@node-minify/core/node_modules/path-scurry/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/@node-minify/terser": {
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/@node-minify/terser/-/terser-8.0.6.tgz",
+ "integrity": "sha512-grQ1ipham743ch2c3++C8Isk6toJnxJSyDiwUI/IWUCh4CZFD6aYVw6UAY40IpCnjrq5aXGwiv5OZJn6Pr0hvg==",
+ "license": "MIT",
+ "dependencies": {
+ "@node-minify/utils": "8.0.6",
+ "terser": "5.16.9"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@node-minify/utils": {
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/@node-minify/utils/-/utils-8.0.6.tgz",
+ "integrity": "sha512-csY4qcR7jUwiZmkreNTJhcypQfts2aY2CK+a+rXgXUImZiZiySh0FvwHjRnlqWKvg+y6ae9lHFzDRjBTmqlTIQ==",
+ "license": "MIT",
+ "dependencies": {
+ "gzip-size": "6.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nolyfill/is-core-module": {
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
+ "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.4.0"
+ }
+ },
+ "node_modules/@opennextjs/aws": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@opennextjs/aws/-/aws-4.0.2.tgz",
+ "integrity": "sha512-nXQPT8GZDV+NWMJV9mD/Ywxyo+tCZfFvrR6jpEOYNcxK/AqiEDlJzPybGOrHUDWAYdR1b6tmh+MoR3VbqIao3w==",
+ "license": "MIT",
+ "dependencies": {
+ "@ast-grep/napi": "^0.40.5",
+ "@aws-sdk/client-cloudfront": "3.984.0",
+ "@aws-sdk/client-dynamodb": "3.984.0",
+ "@aws-sdk/client-lambda": "3.984.0",
+ "@aws-sdk/client-s3": "3.984.0",
+ "@aws-sdk/client-sqs": "3.984.0",
+ "@node-minify/core": "^8.0.6",
+ "@node-minify/terser": "^8.0.6",
+ "@tsconfig/node18": "^1.0.3",
+ "aws4fetch": "^1.0.20",
+ "chalk": "^5.6.2",
+ "cookie": "^1.0.2",
+ "esbuild": "0.25.4",
+ "express": "^5.1.0",
+ "path-to-regexp": "^6.3.0",
+ "urlpattern-polyfill": "^10.1.0",
+ "yaml": "^2.8.1"
+ },
+ "bin": {
+ "open-next": "dist/index.js"
+ },
+ "peerDependencies": {
+ "next": ">=15.5.18 <16 || >=16.2.6"
+ }
+ },
+ "node_modules/@opennextjs/aws/node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@opennextjs/cloudflare": {
+ "version": "1.19.11",
+ "resolved": "https://registry.npmjs.org/@opennextjs/cloudflare/-/cloudflare-1.19.11.tgz",
+ "integrity": "sha512-spZ7YsZZW9q/OJStaZlJhuklYKei5e2tNQ7PMi3DDSJ7x7167m7EYYHQZfVN5gwJBDkMR2jUDW88oHjnGz4YYw==",
+ "license": "MIT",
+ "dependencies": {
+ "@ast-grep/napi": "^0.40.5",
+ "@dotenvx/dotenvx": "1.31.0",
+ "@opennextjs/aws": "4.0.2",
+ "ci-info": "^4.2.0",
+ "cloudflare": "^4.4.1",
+ "comment-json": "^4.5.1",
+ "enquirer": "^2.4.1",
+ "glob": "^12.0.0",
+ "ts-tqdm": "^0.8.6",
+ "yargs": "^18.0.0"
+ },
+ "bin": {
+ "opennextjs-cloudflare": "dist/cli/index.js"
+ },
+ "peerDependencies": {
+ "next": ">=15.5.18 <16 || >=16.2.6",
+ "wrangler": "^4.86.0"
+ }
+ },
+ "node_modules/@poppinss/colors": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz",
+ "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==",
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^4.1.5"
+ }
+ },
+ "node_modules/@poppinss/dumper": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz",
+ "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==",
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/colors": "^4.1.5",
+ "@sindresorhus/is": "^7.0.2",
+ "supports-color": "^10.0.0"
+ }
+ },
+ "node_modules/@poppinss/dumper/node_modules/supports-color": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz",
+ "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/@poppinss/exception": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz",
+ "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==",
+ "license": "MIT"
+ },
+ "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-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-arrow/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-arrow/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-avatar": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz",
+ "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.4",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-is-hydrated": "0.1.0",
+ "@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-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-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-collection/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-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.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-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-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/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-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-dismissable-layer/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-dismissable-layer/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-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-dropdown-menu/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-dropdown-menu/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-dropdown-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-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-focus-scope/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-focus-scope/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-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-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-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-menu/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-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-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-popper/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-popper/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-popper/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-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-portal/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-portal/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-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.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-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-roving-focus/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-roving-focus/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-roving-focus/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-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-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-select/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-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-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-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-tabs/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-tabs/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-tabs/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-is-hydrated": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz",
+ "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==",
+ "license": "MIT",
+ "dependencies": {
+ "use-sync-external-store": "^1.5.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-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/react-visually-hidden/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-visually-hidden/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/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/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.16.1.tgz",
+ "integrity": "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz",
+ "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@smithy/config-resolver": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.5.4.tgz",
+ "integrity": "sha512-jqADOFCkuSqluoEPjxWTFQ/6Xfsmt4Xi3IelA+c+4WdavqCijGGfWi873VqfIZeSFvaBpYeH+PKHC3POE98KlQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/core": {
+ "version": "3.24.4",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.4.tgz",
+ "integrity": "sha512-3UNRKEyQyAgVgM0LGlerCLm+ChZWZ1GPfde+jBEW6bm6bSBGU1p0EbblaUV3unbhwvidjLA5Zs3sOs7mnZwvAw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/credential-provider-imds": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.4.tgz",
+ "integrity": "sha512-vKW0MEFRU4Y3MkVZUkpJm+g9qyPGLCXhc0YLggUdSdBB4g7IaSSsCE75P9rBXyWHrXY1UYSQUl8/DwsTR7QciA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-browser": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.3.4.tgz",
+ "integrity": "sha512-9szC3PfHhYSvWA98CIrD6rB8jS60tfKOPvDlzyD87gsDm8KDnsSpXnwPO1J3bPxg0tWE6Ljzk2YzZV2GBe3nUQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.4.4.tgz",
+ "integrity": "sha512-Q28S5qVeHIGXY4xCO43IFglVCc11HXZlxdhUhcNgiI/ArVDi6SWOMLvWEq1woUQtThNxH3CPbz6l1Z2PT6gl8A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-node": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.3.4.tgz",
+ "integrity": "sha512-QxrsfEjVwpx2rzu0ZRc+F1MFSVh9pnjJayHzxjy3l3ru2zp7yt9FsYnDBHmdZV7389wqc1poK84vf5v3lArSaw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/fetch-http-handler": {
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.4.tgz",
+ "integrity": "sha512-qM7AUKI4G6d7lNgaZD3lA1tWSolh5r6gcixfTZAPstVURfjIbvreVTPz+994M0yC3HbX4YYhDRgr31Xy3XwWOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-blob-browser": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.3.4.tgz",
+ "integrity": "sha512-HQw/cCLjoAatHffbVQxanPfDRYFt3NMhAENub1/Pw0iftGYGSS4+4C+G1D7CCJXW5/wR6AIhLT7xPusMqy7qjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-node": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.3.4.tgz",
+ "integrity": "sha512-LfXN/tUjjmUkEaMWto96a3Xetk7u4WMruzFop7mtsIYY2njTvTQm/zsok9KpwztzOL3WSBfv+hikxkJhArv8xQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-stream-node": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.3.4.tgz",
+ "integrity": "sha512-wuwVYqGNP9RwLs5hU2nTg8ajL16lA27VX7oGrsarghiqOhAtGYWQQ2VNtotKCBra5t4Od+Epi5jYktm0JwDuIQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/invalid-dependency": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.3.4.tgz",
+ "integrity": "sha512-lByqayJi0EC8wAysIA93QwN4C1ofppNk5YXt8QS4Zo2AVHxGWspkwvYGP/5WLO4jsdHDsEc+KAdmqJBP9eN46g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/md5-js": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.3.4.tgz",
+ "integrity": "sha512-drsFcLEIjFtmDF8Ta5STY7zTc89L24qL+G2f+YGo2oeoB3OW/6zjhKwW8/nCTS45AAFSyh81UgJ+Jl+Gs0ovnQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-content-length": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.3.4.tgz",
+ "integrity": "sha512-dI6ysYleXIHUDVsJ8JKR8m9zUNo29y43D6/evJcfY/JREgBrXpWbBavs1EAJIPA5+d7DBlepqSCIWveWiyO1jw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-endpoint": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.5.4.tgz",
+ "integrity": "sha512-vfaUGI2plIGPeiYlUwtC2IccLKR5XwPLCPzMwRF/dDlvMtVuy6L7Klx2LThoU3nENR294j/48Tn9alg/3teV1Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-retry": {
+ "version": "4.6.4",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.6.4.tgz",
+ "integrity": "sha512-KOAlkv0/6yYLLXcJNTWq116q+ezv3i0+TQNg13hExZLUBwLvBj9ipP7f1+sAfVUsfYG/BFuF2nX6BRoKHFqt1Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-serde": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.3.4.tgz",
+ "integrity": "sha512-J6JfVBmp3Z8ALEnIVJOyuBYr+xl/oIEvDY4qc9vbGXdgPZRYEYOrenXGhH7NnC2SDOWtkg8pIGw/yaTZTYDzrA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-stack": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.3.4.tgz",
+ "integrity": "sha512-fMuimMAsXCcDjWSNXeVitzQeWYKxvFmBbWVnYf1qLC5PaFbDBF0DcWQKSnqDY+QaaSzLIh+iAU3TaEWdGEeCfA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-config-provider": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.4.4.tgz",
+ "integrity": "sha512-mD/K1A5WrTZh6I23x1ScYo3K7/+Ujvp/zvLtaZT+xkDeXksWAQ/fKp60SudeUHUHQe/3Q3rgnfedJDqnxSKdpA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-http-handler": {
+ "version": "4.7.4",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.4.tgz",
+ "integrity": "sha512-HIeF+1vrDGzPkkv39Hj2vlHSXHY3p958jd/8ZnePIY6+ZOsQX8coyEUKO5yQu4r0bQIVsbpotVIrXXwyycMStQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/protocol-http": {
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.4.4.tgz",
+ "integrity": "sha512-5VdJYIYsVt2GT+i0fp5gvWoJNrdFEFN16TrpNnAZHngYC/xgk5yni6O/qV3WlIpJjeLC8RfwoQiNTljCdbNXgw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/signature-v4": {
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.4.4.tgz",
+ "integrity": "sha512-e5UtkMvsatzBfbeBZjEOt0k0Z3BEsjTFL/n6fdO5vtBLe67tdy0dX7xw2DU7uZ3acwoHyeCqpU2Fzb7pxwHb6Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/smithy-client": {
+ "version": "4.13.4",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.13.4.tgz",
+ "integrity": "sha512-Lg3hCVv8oVYlnQus1x+1hlNoLSrcdOhkg2+Be5YUxkI1LbCEPpcwEdYfz+0j1sQSmEixA/UUbxW41CiN/+aigA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/types": {
+ "version": "4.14.2",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.2.tgz",
+ "integrity": "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/url-parser": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.3.4.tgz",
+ "integrity": "sha512-Acgxr0W3vdmDNZKafjpDFaG2t32zNYVd7B5D3Y9LQep264+6pP/K/4ZXiAfW+ztMYB0iBG1kZx19EmRBd9zA/g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-base64": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.4.4.tgz",
+ "integrity": "sha512-f3zLXiAzY3oYDdubxW//QLk5KEngThcNQhKvcLGGiYNEzYD7B2PXwLjUZO7joB9wfvihflzPJilMest9Q9bj4Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-browser": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.3.4.tgz",
+ "integrity": "sha512-ddbTlVHnjDflrReo1VlhPpomb0DlgqEhk/I++OS44Y4PEE0QnzOdJemUo439vNYEFjtJvZd1p9CBe/lcxpontg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-node": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.3.4.tgz",
+ "integrity": "sha512-e3pKOHP/UjTV4/2gMdjcgelvX8DGS6Yy3jSLWh47HvsyeD0fc/V4kkSYfhOjEnV4CizPn9gQojj2q9MiZQcJDg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-browser": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.4.4.tgz",
+ "integrity": "sha512-/TWNfyCtJHHIS5taeOQ1qcMUCr5xPqdFntDL5+Sp8sjGj29ZaFUUxlCP+6V//J7MhHZZ2PIe2kMh1YdOpaEPnA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-node": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.3.4.tgz",
+ "integrity": "sha512-kFGsCILX13YE8troSVPB6AdEAzjbhJ/XFCaEgFGEBz1I17+wMVMBO1WxKxU27GlxBFQy643Jy42RgT8wf8X++g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-endpoints": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.5.4.tgz",
+ "integrity": "sha512-RtzPUniH4R49dG8X2MeOi9UzcNwh8C8lEADOGItnAMifxljQgCbuUOpvciX7EnEEJ5H2T2AXvEdOuXSe0bKdaQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-middleware": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.3.4.tgz",
+ "integrity": "sha512-jzWo5fD5FYdGlfqx+kpp5BoOSG+TYQczYY6Ue2QX4linDq+5q6t2/RtO53nABOZjD+qYSSaVd9RalyMIPbxk9Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-retry": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.4.4.tgz",
+ "integrity": "sha512-4upfJJ+jayyqd523zopC5Ad7XxMp+rpeiqh0QtiZGBvdBB7KBBtHVEtraHNnlzkQuytvkU5yyg6Ckf3ApJ3A5Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-stream": {
+ "version": "4.6.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.6.4.tgz",
+ "integrity": "sha512-mkc/JN/fPiaHBAhhp7LbwAQz6RFjrCkYZ4F3OK2ZAWbmkjDQmAyNUmoDcQDVGWF9U+13+fWPszCXFHLP/8NnAA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-utf8": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.3.4.tgz",
+ "integrity": "sha512-s8lfXcv+5C2GjBwGUBqFLgNmhyp9/n4TSKbOzKlIqJ/x0L/zwIxjNBC6DN4xUy59NvOrsiZI1t3tWi4ADUDyNw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.4.4.tgz",
+ "integrity": "sha512-Qt+W1pLeV/gmsXXUKbcolZqSGwnEdcxM7tqZjtGazkJ4feMUX0Vy+mCZGyhCwLvO8qxsrhYlmRZ7FLGUxJ4Scg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@speed-highlight/core": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz",
+ "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/@supabase/auth-js": {
+ "version": "2.106.1",
+ "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.106.1.tgz",
+ "integrity": "sha512-7eyheXfAGwkB9bZewJPs+N3UYt6kra2JG6mIxNEgbkvcO15PLD1e75PTIUEYYl3zrifm3GrpShVl7QZxKrXO/w==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "2.8.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@supabase/cli-darwin-arm64": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-arm64/-/cli-darwin-arm64-2.101.0.tgz",
+ "integrity": "sha512-SoWYzu2CIE+rADWsZH6H0YZYF8nV2YMelZLbjAqzahb5RRgFOTMWGhKCUj6g4KlNvocUnU19JObUJ7oCx/9aHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@supabase/cli-darwin-x64": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-x64/-/cli-darwin-x64-2.101.0.tgz",
+ "integrity": "sha512-rPES03BF9KYkirq3X1Yll+T+eORueRvC858Yp2+2aQMvB4qxi6k+WI+ilCQ7NGzOJ3G0jl/ZG/KsSjZIa4AJ6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@supabase/cli-linux-arm64": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64/-/cli-linux-arm64-2.101.0.tgz",
+ "integrity": "sha512-E+hN1GRIFEi+U1Jf4Omw/gjwpSRTpJ5jai58tQana15AaXt3GCoG7z2YzWVnzD/mvAubTqA7SLHsV+A2lcdTGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@supabase/cli-linux-arm64-musl": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.101.0.tgz",
+ "integrity": "sha512-B5JFFKKpJLLMwn8vWUB7j5euZPytiDOLo9WYXp0mshg45OaFKjRcDImSzBzx4k0W8MK2x75rFEURca90Ic60Ug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@supabase/cli-linux-x64": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-linux-x64/-/cli-linux-x64-2.101.0.tgz",
+ "integrity": "sha512-7iU9uA+8pbmW5uz+yGxU0fM83a+8SH/gtKmSSRZrOu9vIGcugg9gLbN9GlWkG5P7I7wEjnoVKb7Jzea6onSeQA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@supabase/cli-linux-x64-musl": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-linux-x64-musl/-/cli-linux-x64-musl-2.101.0.tgz",
+ "integrity": "sha512-pr9Ar1/aVaQVqjNSfwRgXHWJznQTIaxblGO+hKIl9k55Ajahiq8GConCwx6DjX1Wa9VW//5Dji+O0pkmFSfcHw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@supabase/cli-windows-arm64": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-windows-arm64/-/cli-windows-arm64-2.101.0.tgz",
+ "integrity": "sha512-mSnFDhTIAe9cr1iifv+DTQzpY/0WphywED2YT3yMGeu94jjxrXrreQkywxEaeSXTnc4ys1umtnWOB1CaBlYKag==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@supabase/cli-windows-x64": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@supabase/cli-windows-x64/-/cli-windows-x64-2.101.0.tgz",
+ "integrity": "sha512-xzZpybVWq62VF102abZr1EP3BbA2bYecwYm3G2dJk+6ua7nAIodu1fiGHAvBSR0BLGQmesNb6KCneawNL3XBsQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@supabase/functions-js": {
+ "version": "2.106.1",
+ "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.106.1.tgz",
+ "integrity": "sha512-XbOPnR2mW7jp/EcW447xmGwCa+/Wc00Hkw8t4tUIJjRsHQ4xAESsLKcyLRhRJjJoUnJVXUlC+w0wUxUCM7CG2A==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "2.8.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@supabase/phoenix": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@supabase/phoenix/-/phoenix-0.4.2.tgz",
+ "integrity": "sha512-YSAGnmDAfuleFCVt3CeurQZAhxRfXWeZIIkwp7NhYzQ1UwW6ePSnzsFAiUm/mbCkfoCf70QQHKW/K6RKh52a4A==",
+ "license": "MIT"
+ },
+ "node_modules/@supabase/postgrest-js": {
+ "version": "2.106.1",
+ "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.106.1.tgz",
+ "integrity": "sha512-Qbn6d2lqiqeaBX1Uko0e/hL90dtQGRN6CG2wMVQtJpRFstlVW45qmUTyTOsiB8dYUWu1fWYo4YzJuDbokGv3tQ==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "2.8.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@supabase/realtime-js": {
+ "version": "2.106.1",
+ "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.106.1.tgz",
+ "integrity": "sha512-eQCYri5E8KsjpDgC7g28cOOS2britjUWdNSJluFMainqrMRepzjOnaxqXc3RoAz7H0dxmBrfLUNF6NGP8C+YaA==",
+ "license": "MIT",
+ "dependencies": {
+ "@supabase/phoenix": "^0.4.2",
+ "tslib": "2.8.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@supabase/ssr": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.8.0.tgz",
+ "integrity": "sha512-/PKk8kNFSs8QvvJ2vOww1mF5/c5W8y42duYtXvkOSe+yZKRgTTZywYG2l41pjhNomqESZCpZtXuWmYjFRMV+dw==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.2"
+ },
+ "peerDependencies": {
+ "@supabase/supabase-js": "^2.76.1"
+ }
+ },
+ "node_modules/@supabase/storage-js": {
+ "version": "2.106.1",
+ "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.106.1.tgz",
+ "integrity": "sha512-HWcLIhqinhWKpOQ3WzglR2unjW0eh9J7yOu3IZrZNIEkraK4La/HDvTqndljGsNw0itPtyHhuKBxRoPG1VUARw==",
+ "license": "MIT",
+ "dependencies": {
+ "iceberg-js": "^0.8.1",
+ "tslib": "2.8.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@supabase/supabase-js": {
+ "version": "2.106.1",
+ "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.106.1.tgz",
+ "integrity": "sha512-gP4HurGkGu7Z3xoOCjtAI17BKKp7jpsmwY0Ssbsks9XQRzJ7ZhK7LxfLdBSYgUdgZCQgjRK+Mr7+cl4Gxrk0Rw==",
+ "license": "MIT",
+ "dependencies": {
+ "@supabase/auth-js": "2.106.1",
+ "@supabase/functions-js": "2.106.1",
+ "@supabase/postgrest-js": "2.106.1",
+ "@supabase/realtime-js": "2.106.1",
+ "@supabase/storage-js": "2.106.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz",
+ "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.5",
+ "enhanced-resolve": "^5.21.0",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.32.0",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.3.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz",
+ "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.3.0",
+ "@tailwindcss/oxide-darwin-arm64": "4.3.0",
+ "@tailwindcss/oxide-darwin-x64": "4.3.0",
+ "@tailwindcss/oxide-freebsd-x64": "4.3.0",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.3.0",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.3.0",
+ "@tailwindcss/oxide-linux-x64-musl": "4.3.0",
+ "@tailwindcss/oxide-wasm32-wasi": "4.3.0",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.3.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz",
+ "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz",
+ "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz",
+ "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz",
+ "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz",
+ "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz",
+ "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz",
+ "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz",
+ "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz",
+ "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz",
+ "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.10.0",
+ "@emnapi/runtime": "^1.10.0",
+ "@emnapi/wasi-threads": "^1.2.1",
+ "@napi-rs/wasm-runtime": "^1.1.4",
+ "@tybys/wasm-util": "^0.10.1",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz",
+ "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz",
+ "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/postcss": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.0.tgz",
+ "integrity": "sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "4.3.0",
+ "@tailwindcss/oxide": "4.3.0",
+ "postcss": "^8.5.10",
+ "tailwindcss": "4.3.0"
+ }
+ },
+ "node_modules/@tsconfig/node18": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-1.0.3.tgz",
+ "integrity": "sha512-RbwvSJQsuN9TB04AQbGULYfOGE/RnSFk/FLQ5b0NmDf5Kx2q/lABZbHQPKCO1vZ6Fiwkplu+yb9pGdLy1iGseQ==",
+ "license": "MIT"
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
+ "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "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.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.19.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz",
+ "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.13",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
+ "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^4.0.4"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.15",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz",
+ "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==",
+ "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/@typescript-eslint/eslint-plugin": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.4.tgz",
+ "integrity": "sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.59.4",
+ "@typescript-eslint/type-utils": "8.59.4",
+ "@typescript-eslint/utils": "8.59.4",
+ "@typescript-eslint/visitor-keys": "8.59.4",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.59.4",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.4.tgz",
+ "integrity": "sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.59.4",
+ "@typescript-eslint/types": "8.59.4",
+ "@typescript-eslint/typescript-estree": "8.59.4",
+ "@typescript-eslint/visitor-keys": "8.59.4",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.4.tgz",
+ "integrity": "sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.59.4",
+ "@typescript-eslint/types": "^8.59.4",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.4.tgz",
+ "integrity": "sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.59.4",
+ "@typescript-eslint/visitor-keys": "8.59.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.4.tgz",
+ "integrity": "sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.4.tgz",
+ "integrity": "sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.59.4",
+ "@typescript-eslint/typescript-estree": "8.59.4",
+ "@typescript-eslint/utils": "8.59.4",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.4.tgz",
+ "integrity": "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.4.tgz",
+ "integrity": "sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.59.4",
+ "@typescript-eslint/tsconfig-utils": "8.59.4",
+ "@typescript-eslint/types": "8.59.4",
+ "@typescript-eslint/visitor-keys": "8.59.4",
+ "debug": "^4.4.3",
+ "minimatch": "^10.2.2",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
+ "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "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/@typescript-eslint/utils": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.4.tgz",
+ "integrity": "sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.59.4",
+ "@typescript-eslint/types": "8.59.4",
+ "@typescript-eslint/typescript-estree": "8.59.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.59.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.4.tgz",
+ "integrity": "sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.59.4",
+ "eslint-visitor-keys": "^5.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz",
+ "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz",
+ "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz",
+ "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz",
+ "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz",
+ "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz",
+ "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz",
+ "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz",
+ "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz",
+ "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-loong64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz",
+ "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-loong64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz",
+ "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz",
+ "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz",
+ "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz",
+ "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz",
+ "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz",
+ "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz",
+ "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-openharmony-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz",
+ "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz",
+ "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "1.10.0",
+ "@emnapi/runtime": "1.10.0",
+ "@napi-rs/wasm-runtime": "^1.1.4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz",
+ "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz",
+ "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz",
+ "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/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/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
+ "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
+ "license": "MIT",
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
+ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "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/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-timsort": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz",
+ "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==",
+ "license": "MIT"
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/aws4fetch": {
+ "version": "1.0.20",
+ "resolved": "https://registry.npmjs.org/aws4fetch/-/aws4fetch-1.0.20.tgz",
+ "integrity": "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==",
+ "license": "MIT"
+ },
+ "node_modules/axe-core": {
+ "version": "4.11.4",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.4.tgz",
+ "integrity": "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "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/blake3-wasm": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
+ "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==",
+ "license": "MIT"
+ },
+ "node_modules/body-parser": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.7.0",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.1",
+ "raw-body": "^3.0.1",
+ "type-is": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/bowser": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz",
+ "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==",
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/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==",
+ "dev": true,
+ "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/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001793",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
+ "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==",
+ "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/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/ci-info": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz",
+ "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz",
+ "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^7.2.0",
+ "strip-ansi": "^7.1.0",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/cloudflare": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/cloudflare/-/cloudflare-4.5.0.tgz",
+ "integrity": "sha512-fPcbPKx4zF45jBvQ0z7PCdgejVAPBBCZxwqk1k7krQNfpM07Cfj97/Q6wBzvYqlWXx/zt1S9+m8vnfCe06umbQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/node": "^18.11.18",
+ "@types/node-fetch": "^2.6.4",
+ "abort-controller": "^3.0.0",
+ "agentkeepalive": "^4.2.1",
+ "form-data-encoder": "1.7.2",
+ "formdata-node": "^4.3.2",
+ "node-fetch": "^2.6.7"
+ }
+ },
+ "node_modules/cloudflare/node_modules/@types/node": {
+ "version": "18.19.130",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
+ "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/cloudflare/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "license": "MIT"
+ },
+ "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/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/comment-json": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.6.2.tgz",
+ "integrity": "sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w==",
+ "license": "MIT",
+ "dependencies": {
+ "array-timsort": "^1.0.3",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/content-disposition": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/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/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/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/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/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/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-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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/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/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/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/duplexer": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
+ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
+ "license": "MIT"
+ },
+ "node_modules/eciesjs": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.18.tgz",
+ "integrity": "sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@ecies/ciphers": "^0.2.5",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "^1.9.7",
+ "@noble/hashes": "^1.8.0"
+ },
+ "engines": {
+ "bun": ">=1",
+ "deno": ">=2",
+ "node": ">=16"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "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/enhanced-resolve": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.0.tgz",
+ "integrity": "sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/enquirer": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
+ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-colors": "^4.1.1",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/error-stack-parser-es": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz",
+ "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.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-iterator-helpers": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz",
+ "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.2",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.1.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.3.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",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.5",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",
+ "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.4",
+ "@esbuild/android-arm": "0.25.4",
+ "@esbuild/android-arm64": "0.25.4",
+ "@esbuild/android-x64": "0.25.4",
+ "@esbuild/darwin-arm64": "0.25.4",
+ "@esbuild/darwin-x64": "0.25.4",
+ "@esbuild/freebsd-arm64": "0.25.4",
+ "@esbuild/freebsd-x64": "0.25.4",
+ "@esbuild/linux-arm": "0.25.4",
+ "@esbuild/linux-arm64": "0.25.4",
+ "@esbuild/linux-ia32": "0.25.4",
+ "@esbuild/linux-loong64": "0.25.4",
+ "@esbuild/linux-mips64el": "0.25.4",
+ "@esbuild/linux-ppc64": "0.25.4",
+ "@esbuild/linux-riscv64": "0.25.4",
+ "@esbuild/linux-s390x": "0.25.4",
+ "@esbuild/linux-x64": "0.25.4",
+ "@esbuild/netbsd-arm64": "0.25.4",
+ "@esbuild/netbsd-x64": "0.25.4",
+ "@esbuild/openbsd-arm64": "0.25.4",
+ "@esbuild/openbsd-x64": "0.25.4",
+ "@esbuild/sunos-x64": "0.25.4",
+ "@esbuild/win32-arm64": "0.25.4",
+ "@esbuild/win32-ia32": "0.25.4",
+ "@esbuild/win32-x64": "0.25.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "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/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.18.tgz",
+ "integrity": "sha512-HuoJU6uUPD00eyiud78IBnT4HLhztFj2V+ild2Uon5ZUrYZKe0Olu2QRD99e9IgL4/H1eg5Onka3BsfRW2U0Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@next/eslint-plugin-next": "15.5.18",
+ "@rushstack/eslint-patch": "^1.10.3",
+ "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-jsx-a11y": "^6.10.0",
+ "eslint-plugin-react": "^7.37.0",
+ "eslint-plugin-react-hooks": "^5.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.10",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz",
+ "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.16.1",
+ "resolve": "^2.0.0-next.6"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
+ "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@nolyfill/is-core-module": "1.0.39",
+ "debug": "^4.4.0",
+ "get-tsconfig": "^4.10.0",
+ "is-bun-module": "^2.0.0",
+ "stable-hash": "^0.0.5",
+ "tinyglobby": "^0.2.13",
+ "unrs-resolver": "^1.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-import-resolver-typescript"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
+ "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
+ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.9",
+ "array.prototype.findlastindex": "^1.2.6",
+ "array.prototype.flat": "^1.3.3",
+ "array.prototype.flatmap": "^1.3.3",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.1",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.16.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.1",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.9",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
+ "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aria-query": "^5.3.2",
+ "array-includes": "^3.1.8",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "^4.10.0",
+ "axobject-query": "^4.1.0",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.includes": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+ "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "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/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=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/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express/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/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "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-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-xml-builder": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
+ "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "path-expression-matcher": "^1.5.0",
+ "xml-naming": "^0.1.0"
+ }
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz",
+ "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@nodable/entities": "^2.1.0",
+ "fast-xml-builder": "^1.1.7",
+ "path-expression-matcher": "^1.5.0",
+ "strnum": "^2.2.3"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/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/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "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/form-data-encoder": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
+ "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
+ "license": "MIT"
+ },
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/formdata-node": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
+ "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "1.0.0",
+ "web-streams-polyfill": "4.0.0-beta.3"
+ },
+ "engines": {
+ "node": ">= 12.20"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "license": "ISC"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "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-east-asian-width": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
+ "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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-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-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/glob": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-12.0.0.tgz",
+ "integrity": "sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw==",
+ "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/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob/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/glob/node_modules/brace-expansion": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
+ "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/glob/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/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/gzip-size": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
+ "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "duplexer": "^0.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "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/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/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/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/iceberg-js": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz",
+ "integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "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/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "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/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/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/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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bun-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
+ "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.7.1"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-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==",
+ "dev": true,
+ "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-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "license": "MIT"
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/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/jiti": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "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/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
+ "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
+ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "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"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/lru-cache": {
+ "version": "11.5.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.0.tgz",
+ "integrity": "sha512-5YgH9UJd7wVb9hIouI2adWpgqrrICkt070Dnj8EUY1+B4B2P9eRLPAkAAo6NICA7CEhOIeBHl46u9zSNpNu7zA==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.475.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.475.0.tgz",
+ "integrity": "sha512-NJzvVu1HwFVeZ+Gwq2q00KygM1aBhy/ZrhY9FsAgJtpB+E4R7uxRk9M2iKvHa6/vNxZydIB59htha4c2vvwvVg==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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": "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/merge-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "license": "MIT"
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/miniflare": {
+ "version": "4.20260521.0",
+ "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260521.0.tgz",
+ "integrity": "sha512-roRfxPq49OkuSeQsc43hRjSB1+HdHtDNKRwDEVk2hCjCBuBWxb5Wvwq88b0ULj6QVEJLN/+ZqF19M+h4VYJ/zg==",
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "0.8.1",
+ "sharp": "^0.34.5",
+ "undici": "7.24.8",
+ "workerd": "1.20260521.1",
+ "ws": "8.20.1",
+ "youch": "4.1.0-beta.10"
+ },
+ "bin": {
+ "miniflare": "bootstrap.js"
+ },
+ "engines": {
+ "node": ">=22.0.0"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "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/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mnemonist": {
+ "version": "0.38.3",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz",
+ "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==",
+ "license": "MIT",
+ "dependencies": {
+ "obliterator": "^1.6.1"
+ }
+ },
+ "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/nanoid": {
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
+ "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/napi-postinstall": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
+ "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/next": {
+ "version": "15.5.18",
+ "resolved": "https://registry.npmjs.org/next/-/next-15.5.18.tgz",
+ "integrity": "sha512-eKL8zUJkX9Y5lE+RX/2YJoItVdGlIscyVyboeD9wSpp0PaGqjoA4tTpT2qPqz9ax+5IzGESyLSeZ/RCwbSZ2uQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@next/env": "15.5.18",
+ "@swc/helpers": "0.5.15",
+ "caniuse-lite": "^1.0.30001579",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.6"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "15.5.18",
+ "@next/swc-darwin-x64": "15.5.18",
+ "@next/swc-linux-arm64-gnu": "15.5.18",
+ "@next/swc-linux-arm64-musl": "15.5.18",
+ "@next/swc-linux-x64-gnu": "15.5.18",
+ "@next/swc-linux-x64-musl": "15.5.18",
+ "@next/swc-win32-arm64-msvc": "15.5.18",
+ "@next/swc-win32-x64-msvc": "15.5.18",
+ "sharp": "^0.34.3"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.51.1",
+ "babel-plugin-react-compiler": "*",
+ "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/next/node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "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.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-exports-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz",
+ "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array.prototype.flatmap": "^1.3.3",
+ "es-errors": "^1.3.0",
+ "object.entries": "^1.1.9",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/node-exports-info/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object-treeify": {
+ "version": "1.1.33",
+ "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz",
+ "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obliterator": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz",
+ "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==",
+ "license": "MIT"
+ },
+ "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/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-expression-matcher": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz",
+ "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "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-to-regexp": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
+ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
+ "license": "MIT"
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "license": "MIT"
+ },
+ "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": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.15",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+ "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.12",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "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/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.15.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
+ "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "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": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.2.6",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz",
+ "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.6",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz",
+ "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.6"
+ }
+ },
+ "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/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/recharts": {
+ "version": "2.15.4",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz",
+ "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==",
+ "deprecated": "1.x and 2.x branches are no longer active. Bump to Recharts v3 to receive latest features and bugfixes. See https://github.com/recharts/recharts/wiki/3.0-migration-guide",
+ "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/recharts/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/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "2.0.0-next.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
+ "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.2",
+ "node-exports-info": "^1.6.0",
+ "object-keys": "^1.1.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-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rosie-skills": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/rosie-skills/-/rosie-skills-0.6.4.tgz",
+ "integrity": "sha512-ojfhSiQRdZ2QyWbmKAHOSAUbaLYrTc5zIH7mS1jKoP8KCFSQddwVhMyFqldckTeybTfW3zNcsZzyOTzGTN1SBA==",
+ "license": "BSD-3-Clause",
+ "bin": {
+ "rosie-skills": "dist/bin.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "rosie-skills-darwin-arm64": "0.6.4",
+ "rosie-skills-freebsd-x64": "0.6.4",
+ "rosie-skills-linux-x64": "0.6.4"
+ }
+ },
+ "node_modules/rosie-skills-darwin-arm64": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/rosie-skills-darwin-arm64/-/rosie-skills-darwin-arm64-0.6.4.tgz",
+ "integrity": "sha512-rn1s5hqFKcxeiDEWWoFa1hdGPshR8TkwHLzy/cBavb9XJNAaUxbe3oQ78W9sQkRHAgRyzJYyk9tw68Qrdnizgg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/rosie-skills-freebsd-x64": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/rosie-skills-freebsd-x64/-/rosie-skills-freebsd-x64-0.6.4.tgz",
+ "integrity": "sha512-SxCRduPBMtfjkQ+q56Yw9OLA3PyaqoALzt7kER7IDKuUVfM2O/1w8sa5xhTDiCvWkZJixnH5d5Ya6KT+/Mwcng==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/rosie-skills-linux-x64": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/rosie-skills-linux-x64/-/rosie-skills-linux-x64-0.6.4.tgz",
+ "integrity": "sha512-D9Y9mfu7goB0s0X59uU3hcFeUTef3VbpCIDwFMzyvJrAq3XhRACWBDMHQsHlyWdHxTXPX/ILyW65RXyrJlgqng==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/router/node_modules/path-to-regexp": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "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/semver": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz",
+ "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.1",
+ "mime-types": "^3.0.2",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "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",
+ "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/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.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/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "license": "ISC"
+ },
+ "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/stable-hash": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
+ "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
+ "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/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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
+ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
+ "license": "MIT"
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/string.prototype.includes": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
+ "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
+ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "regexp.prototype.flags": "^1.5.3",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "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/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-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz",
+ "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
+ "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
+ "license": "MIT",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/supabase": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/supabase/-/supabase-2.101.0.tgz",
+ "integrity": "sha512-9wqlvXGeI+VjOMUKOGEpcZzTJGLia6IOv8LWN3W2u8F6Xiv4ZqAuTuXCp3MWfkhV5x9KQaBtN5d6IiLEMWzkJA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "supabase": "dist/supabase.js"
+ },
+ "optionalDependencies": {
+ "@supabase/cli-darwin-arm64": "2.101.0",
+ "@supabase/cli-darwin-x64": "2.101.0",
+ "@supabase/cli-linux-arm64": "2.101.0",
+ "@supabase/cli-linux-arm64-musl": "2.101.0",
+ "@supabase/cli-linux-x64": "2.101.0",
+ "@supabase/cli-linux-x64-musl": "2.101.0",
+ "@supabase/cli-windows-arm64": "2.101.0",
+ "@supabase/cli-windows-x64": "2.101.0"
+ }
+ },
+ "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/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tailwind-merge": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz",
+ "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz",
+ "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.16.9",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz",
+ "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.2",
+ "acorn": "^8.5.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser/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/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/tinyglobby": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+ "dev": true,
+ "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/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
+ "node_modules/ts-api-utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+ "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/ts-tqdm": {
+ "version": "0.8.6",
+ "resolved": "https://registry.npmjs.org/ts-tqdm/-/ts-tqdm-0.8.6.tgz",
+ "integrity": "sha512-3X3M1PZcHtgQbnwizL+xU8CAgbYbeLHrrDwL9xxcZZrV5J+e7loJm1XrXozHjSkl44J0Zg0SgA8rXbh83kCkcQ==",
+ "license": "MIT"
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
+ "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==",
+ "license": "MIT",
+ "dependencies": {
+ "content-type": "^2.0.0",
+ "media-typer": "^1.1.0",
+ "mime-types": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/type-is/node_modules/content-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
+ "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.8.tgz",
+ "integrity": "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "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/unenv": {
+ "version": "2.0.0-rc.24",
+ "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz",
+ "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==",
+ "license": "MIT",
+ "dependencies": {
+ "pathe": "^2.0.3"
+ }
+ },
+ "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/unrs-resolver": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz",
+ "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "napi-postinstall": "^0.3.4"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unrs-resolver"
+ },
+ "optionalDependencies": {
+ "@unrs/resolver-binding-android-arm-eabi": "1.12.2",
+ "@unrs/resolver-binding-android-arm64": "1.12.2",
+ "@unrs/resolver-binding-darwin-arm64": "1.12.2",
+ "@unrs/resolver-binding-darwin-x64": "1.12.2",
+ "@unrs/resolver-binding-freebsd-x64": "1.12.2",
+ "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2",
+ "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2",
+ "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-arm64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-loong64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-x64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-x64-musl": "1.12.2",
+ "@unrs/resolver-binding-openharmony-arm64": "1.12.2",
+ "@unrs/resolver-binding-wasm32-wasi": "1.12.2",
+ "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2",
+ "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2",
+ "@unrs/resolver-binding-win32-x64-msvc": "1.12.2"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/urlpattern-polyfill": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz",
+ "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==",
+ "license": "MIT"
+ },
+ "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/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/web-streams-polyfill": {
+ "version": "4.0.0-beta.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
+ "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
+ "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/workerd": {
+ "version": "1.20260521.1",
+ "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260521.1.tgz",
+ "integrity": "sha512-HzIThcZ0ZVEuzVxpY2IYZ3yssSrTjtrWXAVfmOl5rVwyqcu7aeZXGMiwrEmi9MOcC3wjy+BNv+hFrMMY5OrjQQ==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "workerd": "bin/workerd"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "optionalDependencies": {
+ "@cloudflare/workerd-darwin-64": "1.20260521.1",
+ "@cloudflare/workerd-darwin-arm64": "1.20260521.1",
+ "@cloudflare/workerd-linux-64": "1.20260521.1",
+ "@cloudflare/workerd-linux-arm64": "1.20260521.1",
+ "@cloudflare/workerd-windows-64": "1.20260521.1"
+ }
+ },
+ "node_modules/wrangler": {
+ "version": "4.94.0",
+ "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.94.0.tgz",
+ "integrity": "sha512-GsNw0DomGFfeXFtKVTwn2X69UKcCxcTB0CXykjsMineJIxOeyrw7LovlHQ/3JU8KJHH7repLB+kOHvfTBA/Eew==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@cloudflare/kv-asset-handler": "0.5.0",
+ "@cloudflare/unenv-preset": "2.16.1",
+ "blake3-wasm": "2.1.5",
+ "esbuild": "0.27.3",
+ "miniflare": "4.20260521.0",
+ "path-to-regexp": "6.3.0",
+ "rosie-skills": "^0.6.3",
+ "unenv": "2.0.0-rc.24",
+ "workerd": "1.20260521.1"
+ },
+ "bin": {
+ "wrangler": "bin/wrangler.js",
+ "wrangler2": "bin/wrangler.js"
+ },
+ "engines": {
+ "node": ">=22.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@cloudflare/workers-types": "^4.20260521.1"
+ },
+ "peerDependenciesMeta": {
+ "@cloudflare/workers-types": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
+ "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/android-arm": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
+ "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/android-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
+ "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/android-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
+ "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
+ "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
+ "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
+ "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-arm": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
+ "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
+ "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
+ "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
+ "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
+ "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
+ "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
+ "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
+ "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
+ "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
+ "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
+ "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
+ "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
+ "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
+ "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/win32-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
+ "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/esbuild": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
+ "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.3",
+ "@esbuild/android-arm": "0.27.3",
+ "@esbuild/android-arm64": "0.27.3",
+ "@esbuild/android-x64": "0.27.3",
+ "@esbuild/darwin-arm64": "0.27.3",
+ "@esbuild/darwin-x64": "0.27.3",
+ "@esbuild/freebsd-arm64": "0.27.3",
+ "@esbuild/freebsd-x64": "0.27.3",
+ "@esbuild/linux-arm": "0.27.3",
+ "@esbuild/linux-arm64": "0.27.3",
+ "@esbuild/linux-ia32": "0.27.3",
+ "@esbuild/linux-loong64": "0.27.3",
+ "@esbuild/linux-mips64el": "0.27.3",
+ "@esbuild/linux-ppc64": "0.27.3",
+ "@esbuild/linux-riscv64": "0.27.3",
+ "@esbuild/linux-s390x": "0.27.3",
+ "@esbuild/linux-x64": "0.27.3",
+ "@esbuild/netbsd-arm64": "0.27.3",
+ "@esbuild/netbsd-x64": "0.27.3",
+ "@esbuild/openbsd-arm64": "0.27.3",
+ "@esbuild/openbsd-x64": "0.27.3",
+ "@esbuild/openharmony-arm64": "0.27.3",
+ "@esbuild/sunos-x64": "0.27.3",
+ "@esbuild/win32-arm64": "0.27.3",
+ "@esbuild/win32-ia32": "0.27.3",
+ "@esbuild/win32-x64": "0.27.3"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/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.20.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
+ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
+ "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/xml-naming": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz",
+ "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "18.0.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz",
+ "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^9.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "string-width": "^7.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^22.0.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=23"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "22.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz",
+ "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==",
+ "license": "ISC",
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=23"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/youch": {
+ "version": "4.1.0-beta.10",
+ "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz",
+ "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/colors": "^4.1.5",
+ "@poppinss/dumper": "^0.6.4",
+ "@speed-highlight/core": "^1.2.7",
+ "cookie": "^1.0.2",
+ "youch-core": "^0.3.3"
+ }
+ },
+ "node_modules/youch-core": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz",
+ "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==",
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/exception": "^1.2.2",
+ "error-stack-parser-es": "^1.0.5"
+ }
+ },
+ "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
new file mode 100644
index 0000000..048376e
--- /dev/null
+++ b/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "yaltopia-fifa",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
+ "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
+ "upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload",
+ "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
+ "db:push": "npx supabase db push",
+ "db:push:pooler": "node ./scripts/db-push-pooler.mjs",
+ "db:link": "node ./scripts/link-ipv4.mjs",
+ "auth:reset-password": "node ./scripts/reset-user-password.mjs"
+ },
+ "dependencies": {
+ "@radix-ui/react-avatar": "^1.1.3",
+ "@radix-ui/react-dialog": "^1.1.6",
+ "@radix-ui/react-dropdown-menu": "^2.1.6",
+ "@radix-ui/react-label": "^2.1.2",
+ "@radix-ui/react-select": "^2.1.6",
+ "@radix-ui/react-slot": "^1.1.2",
+ "@radix-ui/react-tabs": "^1.1.3",
+ "@opennextjs/cloudflare": "^1.6.0",
+ "@supabase/ssr": "^0.8.0",
+ "@supabase/supabase-js": "^2.86.0",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.475.0",
+ "next": "^15.2.0",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "recharts": "^2.15.1",
+ "tailwind-merge": "^3.0.1",
+ "zod": "^3.24.2"
+ },
+ "devDependencies": {
+ "wrangler": "^4.0.0",
+ "supabase": "^2.101.0",
+ "@eslint/eslintrc": "^3.0.0",
+ "@tailwindcss/postcss": "^4.0.9",
+ "@types/node": "^22.0.0",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
+ "eslint": "^9.0.0",
+ "eslint-config-next": "^15.2.0",
+ "tailwindcss": "^4.0.9",
+ "typescript": "^5.0.0"
+ }
+}
diff --git a/postcss.config.mjs b/postcss.config.mjs
new file mode 100644
index 0000000..61e3684
--- /dev/null
+++ b/postcss.config.mjs
@@ -0,0 +1,7 @@
+const config = {
+ plugins: {
+ "@tailwindcss/postcss": {},
+ },
+};
+
+export default config;
diff --git a/public/_headers b/public/_headers
new file mode 100644
index 0000000..0a731a1
--- /dev/null
+++ b/public/_headers
@@ -0,0 +1,2 @@
+/_next/static/*
+ Cache-Control: public,max-age=31536000,immutable
diff --git a/scripts/db-push-pooler.mjs b/scripts/db-push-pooler.mjs
new file mode 100644
index 0000000..c8f8239
--- /dev/null
+++ b/scripts/db-push-pooler.mjs
@@ -0,0 +1,51 @@
+import { spawnSync } from "child_process";
+import { readFileSync, existsSync } from "fs";
+import { dirname, join } from "path";
+import { fileURLToPath } from "url";
+
+const root = join(dirname(fileURLToPath(import.meta.url)), "..");
+
+function loadEnvLocal() {
+ const path = join(root, ".env.local");
+ if (!existsSync(path)) return {};
+ const env = {};
+ for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) continue;
+ const eq = trimmed.indexOf("=");
+ if (eq === -1) continue;
+ const key = trimmed.slice(0, eq).trim();
+ let val = trimmed.slice(eq + 1).trim();
+ if (
+ (val.startsWith('"') && val.endsWith('"')) ||
+ (val.startsWith("'") && val.endsWith("'"))
+ ) {
+ val = val.slice(1, -1);
+ }
+ env[key] = val;
+ }
+ return env;
+}
+
+const env = loadEnvLocal();
+const dbUrl = env.SUPABASE_DB_URL;
+
+if (!dbUrl) {
+ console.error("ERROR: SUPABASE_DB_URL is not set in .env.local\n");
+ console.error("1. Open https://supabase.com/dashboard/project/vcxpcyafnlyiyqmapyyy");
+ console.error("2. Connect -> Session mode (port 5432)");
+ console.error("3. Add to .env.local:");
+ console.error(
+ " SUPABASE_DB_URL=postgresql://postgres.vcxpcyafnlyiyqmapyyy:PASSWORD@aws-0-REGION.pooler.supabase.com:5432/postgres"
+ );
+ process.exit(1);
+}
+
+console.log("Pushing migrations via pooler (IPv4)...");
+const result = spawnSync("npx", ["supabase", "db", "push", "--db-url", dbUrl], {
+ cwd: root,
+ stdio: "inherit",
+ shell: true,
+});
+
+process.exit(result.status ?? 1);
diff --git a/scripts/link-ipv4.mjs b/scripts/link-ipv4.mjs
new file mode 100644
index 0000000..32cf154
--- /dev/null
+++ b/scripts/link-ipv4.mjs
@@ -0,0 +1,54 @@
+import { spawnSync } from "child_process";
+import { readFileSync, existsSync } from "fs";
+import { dirname, join } from "path";
+import { fileURLToPath } from "url";
+
+const root = join(dirname(fileURLToPath(import.meta.url)), "..");
+const projectRef = "vcxpcyafnlyiyqmapyyy";
+
+function loadEnvLocal() {
+ const path = join(root, ".env.local");
+ if (!existsSync(path)) return {};
+ const env = {};
+ for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) continue;
+ const eq = trimmed.indexOf("=");
+ if (eq === -1) continue;
+ const key = trimmed.slice(0, eq).trim();
+ let val = trimmed.slice(eq + 1).trim();
+ if (
+ (val.startsWith('"') && val.endsWith('"')) ||
+ (val.startsWith("'") && val.endsWith("'"))
+ ) {
+ val = val.slice(1, -1);
+ }
+ env[key] = val;
+ }
+ return env;
+}
+
+const env = loadEnvLocal();
+const args = ["supabase", "link", "--project-ref", projectRef];
+
+if (env.SUPABASE_DB_PASSWORD) {
+ console.log(`Linking project ${projectRef} (password from .env.local)...`);
+ args.push("--password", env.SUPABASE_DB_PASSWORD);
+} else {
+ console.log(`Linking project ${projectRef}...`);
+ console.log(
+ "Enter your database password when prompted (Dashboard -> Settings -> Database)."
+ );
+}
+
+const result = spawnSync("npx", args, {
+ cwd: root,
+ stdio: "inherit",
+ shell: true,
+});
+
+if (result.status === 0) {
+ console.log("\nDone. Run: npm run db:push");
+}
+
+process.exit(result.status ?? 1);
diff --git a/scripts/reset-user-password.mjs b/scripts/reset-user-password.mjs
new file mode 100644
index 0000000..5711104
--- /dev/null
+++ b/scripts/reset-user-password.mjs
@@ -0,0 +1,97 @@
+/**
+ * Dev/admin: set a user's password without sending email (bypasses 429 rate limits).
+ *
+ * Requires in .env.local:
+ * NEXT_PUBLIC_SUPABASE_URL
+ * SUPABASE_SERVICE_ROLE_KEY (Dashboard → Project Settings → API → service_role)
+ *
+ * Usage:
+ * npm run auth:reset-password -- you@example.com YourNewPassword
+ */
+import { createClient } from "@supabase/supabase-js";
+import { readFileSync, existsSync } from "fs";
+import { dirname, join } from "path";
+import { fileURLToPath } from "url";
+
+const root = join(dirname(fileURLToPath(import.meta.url)), "..");
+
+function loadEnvLocal() {
+ const path = join(root, ".env.local");
+ if (!existsSync(path)) return {};
+ const env = {};
+ for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) continue;
+ const eq = trimmed.indexOf("=");
+ if (eq === -1) continue;
+ const key = trimmed.slice(0, eq).trim();
+ let val = trimmed.slice(eq + 1).trim();
+ if (
+ (val.startsWith('"') && val.endsWith('"')) ||
+ (val.startsWith("'") && val.endsWith("'"))
+ ) {
+ val = val.slice(1, -1);
+ }
+ env[key] = val;
+ }
+ return env;
+}
+
+const [, , emailArg, passwordArg] = process.argv;
+const email = emailArg?.trim().toLowerCase();
+const password = passwordArg;
+
+if (!email || !password) {
+ console.error(
+ "Usage: npm run auth:reset-password -- \n"
+ );
+ process.exit(1);
+}
+
+if (password.length < 6) {
+ console.error("Password must be at least 6 characters.");
+ process.exit(1);
+}
+
+const env = loadEnvLocal();
+const url = env.NEXT_PUBLIC_SUPABASE_URL;
+const serviceKey = env.SUPABASE_SERVICE_ROLE_KEY;
+
+if (!url || !serviceKey) {
+ console.error(
+ "Missing NEXT_PUBLIC_SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY in .env.local"
+ );
+ process.exit(1);
+}
+
+const admin = createClient(url, serviceKey, {
+ auth: { autoRefreshToken: false, persistSession: false },
+});
+
+const { data: list, error: listError } = await admin.auth.admin.listUsers({
+ page: 1,
+ perPage: 1000,
+});
+
+if (listError) {
+ console.error("listUsers failed:", listError.message);
+ process.exit(1);
+}
+
+const user = list.users.find((u) => u.email?.toLowerCase() === email);
+if (!user) {
+ console.error(`No user found with email: ${email}`);
+ process.exit(1);
+}
+
+const { error: updateError } = await admin.auth.admin.updateUserById(user.id, {
+ password,
+});
+
+if (updateError) {
+ console.error("updateUserById failed:", updateError.message);
+ process.exit(1);
+}
+
+console.log(`Password updated for ${email} (${user.id})`);
+console.log("Sign in at /login/manager or /login/master with the new password.");
diff --git a/supabase/.temp/project-ref b/supabase/.temp/project-ref
new file mode 100644
index 0000000..1ffd224
--- /dev/null
+++ b/supabase/.temp/project-ref
@@ -0,0 +1 @@
+vcxpcyafnlyiyqmapyyy
\ No newline at end of file
diff --git a/supabase/CONNECTING.md b/supabase/CONNECTING.md
new file mode 100644
index 0000000..f669e5d
--- /dev/null
+++ b/supabase/CONNECTING.md
@@ -0,0 +1,48 @@
+# Fixing IPv6 / `db push` connection errors
+
+If you see:
+
+```
+IPv6 is not supported on your current network
+Run supabase link --project-ref vcxpcyafnlyiyqmapyyy to setup IPv4 connection.
+```
+
+Your network cannot reach Supabase’s **direct** database host (`db.*.supabase.co`, IPv6). Use the **Session pooler** (IPv4) instead.
+
+## Option A — Link once (recommended)
+
+```bash
+npm run db:link
+# Enter your database password when prompted
+npm run db:push
+```
+
+Or with password in `.env.local`:
+
+```bash
+# Add: SUPABASE_DB_PASSWORD=your-database-password
+npm run db:link
+npm run db:push
+```
+
+## Option B — Push with pooler URL (no link)
+
+1. Dashboard → **Connect** → **Session mode** (port **5432**)
+2. Copy the connection string (host looks like `aws-0-….pooler.supabase.com`)
+3. Add to `.env.local`:
+
+```env
+SUPABASE_DB_URL=postgresql://postgres.vcxpcyafnlyiyqmapyyy:YOUR_PASSWORD@aws-0-YOUR_REGION.pooler.supabase.com:5432/postgres
+```
+
+4. Run:
+
+```bash
+npm run db:push:pooler
+```
+
+## Option C — SQL Editor (no CLI)
+
+Run each file in `supabase/migrations/` in order in the [SQL Editor](https://supabase.com/dashboard/project/vcxpcyafnlyiyqmapyyy/sql).
+
+Database password: **Project Settings → Database → Database password**.
diff --git a/supabase/config.toml b/supabase/config.toml
new file mode 100644
index 0000000..0bd3ebf
--- /dev/null
+++ b/supabase/config.toml
@@ -0,0 +1,17 @@
+# Supabase local development config
+# See https://supabase.com/docs/guides/local-development/cli/config
+# Project ref matches NEXT_PUBLIC_SUPABASE_URL (vcxpcyafnlyiyqmapyyy.supabase.co)
+
+project_id = "vcxpcyafnlyiyqmapyyy"
+
+[api]
+enabled = true
+port = 54321
+
+[db]
+port = 54322
+major_version = 15
+
+[studio]
+enabled = true
+port = 54323
diff --git a/supabase/migrations/20250524000001_initial_schema.sql b/supabase/migrations/20250524000001_initial_schema.sql
new file mode 100644
index 0000000..8e5060f
--- /dev/null
+++ b/supabase/migrations/20250524000001_initial_schema.sql
@@ -0,0 +1,268 @@
+-- Yaltopia FIFA Tournament System - Initial Schema
+
+-- Extensions
+CREATE EXTENSION IF NOT EXISTS "pgcrypto";
+
+-- Enums
+CREATE TYPE player_status AS ENUM ('active', 'inactive');
+CREATE TYPE team_member_role AS ENUM ('manager', 'captain');
+CREATE TYPE tournament_mode AS ENUM ('league', 'cup');
+CREATE TYPE competition_status AS ENUM ('draft', 'active', 'playoffs', 'completed');
+CREATE TYPE match_status AS ENUM (
+ 'scheduled',
+ 'schedule_pending',
+ 'schedule_confirmed',
+ 'awaiting_results',
+ 'result_submitted',
+ 'pending_approval',
+ 'disputed',
+ 'completed',
+ 'cancelled'
+);
+CREATE TYPE result_status AS ENUM (
+ 'awaiting_results',
+ 'result_submitted',
+ 'pending_approval',
+ 'disputed',
+ 'completed'
+);
+CREATE TYPE roster_event_type AS ENUM ('add', 'remove');
+CREATE TYPE transfer_status AS ENUM ('pending', 'completed', 'voided');
+CREATE TYPE signature_type AS ENUM ('schedule');
+
+-- Profiles
+CREATE TABLE profiles (
+ id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
+ display_name TEXT,
+ avatar_url TEXT,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Leagues
+CREATE TABLE leagues (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ name TEXT NOT NULL,
+ slug TEXT NOT NULL UNIQUE,
+ description TEXT,
+ created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Versioned league rules
+CREATE TABLE league_rules (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ league_id UUID NOT NULL REFERENCES leagues(id) ON DELETE CASCADE,
+ version INT NOT NULL,
+ rules JSONB NOT NULL DEFAULT '{}',
+ created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ UNIQUE (league_id, version)
+);
+
+-- Competitions (seasons / cups)
+CREATE TABLE competitions (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ league_id UUID NOT NULL REFERENCES leagues(id) ON DELETE CASCADE,
+ name TEXT NOT NULL,
+ tournament_mode tournament_mode NOT NULL DEFAULT 'league',
+ status competition_status NOT NULL DEFAULT 'draft',
+ timezone TEXT NOT NULL DEFAULT 'UTC',
+ rules_snapshot JSONB,
+ rule_set_version INT,
+ created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Global player registry
+CREATE TABLE players (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ display_name TEXT NOT NULL,
+ external_id TEXT,
+ status player_status NOT NULL DEFAULT 'active',
+ created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Teams
+CREATE TABLE teams (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ competition_id UUID NOT NULL REFERENCES competitions(id) ON DELETE CASCADE,
+ name TEXT NOT NULL,
+ logo_path TEXT,
+ home_stadium_name TEXT,
+ cup_seed INT,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Team members (manager / captain)
+CREATE TABLE team_members (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
+ role team_member_role NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ UNIQUE (team_id, user_id)
+);
+
+-- Team availability windows
+CREATE TABLE team_availability (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ day_of_week INT NOT NULL CHECK (day_of_week >= 0 AND day_of_week <= 6),
+ start_time TIME,
+ end_time TIME,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Roster
+CREATE TABLE team_roster (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ player_id UUID NOT NULL REFERENCES players(id) ON DELETE RESTRICT,
+ competition_id UUID NOT NULL REFERENCES competitions(id) ON DELETE CASCADE,
+ joined_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ left_at TIMESTAMPTZ
+);
+
+-- Roster events
+CREATE TABLE roster_events (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ player_id UUID NOT NULL REFERENCES players(id) ON DELETE RESTRICT,
+ competition_id UUID NOT NULL REFERENCES competitions(id) ON DELETE CASCADE,
+ event_type roster_event_type NOT NULL,
+ registered_by UUID NOT NULL REFERENCES auth.users(id),
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Transfers
+CREATE TABLE transfers (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ competition_id UUID NOT NULL REFERENCES competitions(id) ON DELETE CASCADE,
+ player_id UUID NOT NULL REFERENCES players(id) ON DELETE RESTRICT,
+ from_team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ to_team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ status transfer_status NOT NULL DEFAULT 'completed',
+ effective_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ registered_by UUID NOT NULL REFERENCES auth.users(id),
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Competition league managers
+CREATE TABLE competition_league_managers (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ competition_id UUID NOT NULL REFERENCES competitions(id) ON DELETE CASCADE,
+ user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ UNIQUE (competition_id, user_id)
+);
+
+-- Matches
+CREATE TABLE matches (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ competition_id UUID NOT NULL REFERENCES competitions(id) ON DELETE CASCADE,
+ home_team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ away_team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ round INT,
+ matchday INT,
+ leg INT DEFAULT 1,
+ bracket_round INT,
+ bracket_slot INT,
+ next_match_id UUID REFERENCES matches(id) ON DELETE SET NULL,
+ status match_status NOT NULL DEFAULT 'scheduled',
+ result_status result_status DEFAULT 'awaiting_results',
+ scheduled_at TIMESTAMPTZ,
+ proposed_scheduled_at TIMESTAMPTZ,
+ venue TEXT,
+ home_score INT,
+ away_score INT,
+ approved_by UUID REFERENCES auth.users(id),
+ approved_at TIMESTAMPTZ,
+ resolution_note TEXT,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+-- Schedule signatures
+CREATE TABLE match_signatures (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ match_id UUID NOT NULL REFERENCES matches(id) ON DELETE CASCADE,
+ team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
+ signature_type signature_type NOT NULL DEFAULT 'schedule',
+ signed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ UNIQUE (match_id, team_id, signature_type)
+);
+
+-- Result submissions (per team)
+CREATE TABLE match_result_submissions (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ match_id UUID NOT NULL REFERENCES matches(id) ON DELETE CASCADE,
+ team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ home_score INT NOT NULL,
+ away_score INT NOT NULL,
+ submitted_by UUID NOT NULL REFERENCES auth.users(id),
+ submitted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ UNIQUE (match_id, team_id)
+);
+
+-- Player match stats
+CREATE TABLE match_player_stats (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ match_id UUID NOT NULL REFERENCES matches(id) ON DELETE CASCADE,
+ player_id UUID NOT NULL REFERENCES players(id) ON DELETE RESTRICT,
+ team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
+ goals INT NOT NULL DEFAULT 0 CHECK (goals >= 0),
+ assists INT NOT NULL DEFAULT 0 CHECK (assists >= 0),
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ UNIQUE (match_id, player_id)
+);
+
+-- Indexes
+CREATE INDEX idx_competitions_league ON competitions(league_id);
+CREATE INDEX idx_teams_competition ON teams(competition_id);
+CREATE INDEX idx_matches_competition ON matches(competition_id);
+CREATE INDEX idx_matches_status ON matches(competition_id, status);
+CREATE INDEX idx_team_roster_active ON team_roster(competition_id, player_id) WHERE left_at IS NULL;
+CREATE INDEX idx_team_members_user ON team_members(user_id);
+
+-- One manager per team
+CREATE UNIQUE INDEX idx_one_manager_per_team ON team_members(team_id) WHERE role = 'manager';
+
+-- One active roster slot per player per competition
+CREATE UNIQUE INDEX idx_active_roster_per_player ON team_roster(competition_id, player_id) WHERE left_at IS NULL;
+
+-- Updated_at trigger
+CREATE OR REPLACE FUNCTION update_updated_at()
+RETURNS TRIGGER AS $$
+BEGIN
+ NEW.updated_at = now();
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER profiles_updated_at BEFORE UPDATE ON profiles FOR EACH ROW EXECUTE FUNCTION update_updated_at();
+CREATE TRIGGER leagues_updated_at BEFORE UPDATE ON leagues FOR EACH ROW EXECUTE FUNCTION update_updated_at();
+CREATE TRIGGER competitions_updated_at BEFORE UPDATE ON competitions FOR EACH ROW EXECUTE FUNCTION update_updated_at();
+CREATE TRIGGER teams_updated_at BEFORE UPDATE ON teams FOR EACH ROW EXECUTE FUNCTION update_updated_at();
+CREATE TRIGGER players_updated_at BEFORE UPDATE ON players FOR EACH ROW EXECUTE FUNCTION update_updated_at();
+CREATE TRIGGER matches_updated_at BEFORE UPDATE ON matches FOR EACH ROW EXECUTE FUNCTION update_updated_at();
+
+-- Auto-create profile on signup
+CREATE OR REPLACE FUNCTION handle_new_user()
+RETURNS TRIGGER AS $$
+BEGIN
+ INSERT INTO public.profiles (id, display_name)
+ VALUES (NEW.id, COALESCE(NEW.raw_user_meta_data->>'display_name', NEW.email));
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+CREATE TRIGGER on_auth_user_created
+ AFTER INSERT ON auth.users
+ FOR EACH ROW EXECUTE FUNCTION handle_new_user();
diff --git a/supabase/migrations/20250524000002_views.sql b/supabase/migrations/20250524000002_views.sql
new file mode 100644
index 0000000..f4774e1
--- /dev/null
+++ b/supabase/migrations/20250524000002_views.sql
@@ -0,0 +1,105 @@
+-- Standings view (league mode)
+CREATE OR REPLACE VIEW competition_standings AS
+SELECT
+ t.competition_id,
+ t.id AS team_id,
+ t.name AS team_name,
+ t.logo_path,
+ COUNT(m.id) FILTER (WHERE m.status = 'completed') AS played,
+ COUNT(m.id) FILTER (
+ WHERE m.status = 'completed'
+ AND (
+ (m.home_team_id = t.id AND m.home_score > m.away_score)
+ OR (m.away_team_id = t.id AND m.away_score > m.home_score)
+ )
+ ) AS won,
+ COUNT(m.id) FILTER (
+ WHERE m.status = 'completed' AND m.home_score = m.away_score
+ ) AS drawn,
+ COUNT(m.id) FILTER (
+ WHERE m.status = 'completed'
+ AND (
+ (m.home_team_id = t.id AND m.home_score < m.away_score)
+ OR (m.away_team_id = t.id AND m.away_score < m.home_score)
+ )
+ ) AS lost,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status = 'completed' AND m.home_team_id = t.id THEN m.home_score
+ WHEN m.status = 'completed' AND m.away_team_id = t.id THEN m.away_score
+ ELSE 0
+ END
+ ), 0)::INT AS goals_for,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status = 'completed' AND m.home_team_id = t.id THEN m.away_score
+ WHEN m.status = 'completed' AND m.away_team_id = t.id THEN m.home_score
+ ELSE 0
+ END
+ ), 0)::INT AS goals_against,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status = 'completed' AND m.home_team_id = t.id THEN m.home_score - m.away_score
+ WHEN m.status = 'completed' AND m.away_team_id = t.id THEN m.away_score - m.home_score
+ ELSE 0
+ END
+ ), 0)::INT AS goal_difference,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status <> 'completed' THEN 0
+ WHEN m.home_score = m.away_score THEN 1
+ WHEN m.home_team_id = t.id AND m.home_score > m.away_score THEN 3
+ WHEN m.away_team_id = t.id AND m.away_score > m.home_score THEN 3
+ ELSE 0
+ END
+ ), 0)::INT AS points
+FROM teams t
+LEFT JOIN matches m ON m.competition_id = t.competition_id
+ AND (m.home_team_id = t.id OR m.away_team_id = t.id)
+GROUP BY t.competition_id, t.id, t.name, t.logo_path;
+
+-- Player competition stats
+CREATE OR REPLACE VIEW player_competition_stats AS
+SELECT
+ mps.player_id,
+ p.display_name AS player_name,
+ m.competition_id,
+ mps.team_id,
+ COUNT(DISTINCT mps.match_id) AS appearances,
+ COALESCE(SUM(mps.goals), 0)::INT AS goals,
+ COALESCE(SUM(mps.assists), 0)::INT AS assists
+FROM match_player_stats mps
+JOIN matches m ON m.id = mps.match_id AND m.status = 'completed'
+JOIN players p ON p.id = mps.player_id
+GROUP BY mps.player_id, p.display_name, m.competition_id, mps.team_id;
+
+-- Team match results for charts
+CREATE OR REPLACE VIEW team_match_results AS
+SELECT
+ t.id AS team_id,
+ t.competition_id,
+ m.id AS match_id,
+ m.matchday,
+ m.scheduled_at,
+ CASE WHEN m.home_team_id = t.id THEN ht.name ELSE at.name END AS opponent_name,
+ CASE WHEN m.home_team_id = t.id THEN at.logo_path ELSE ht.logo_path END AS opponent_logo,
+ CASE WHEN m.home_team_id = t.id THEN m.home_score ELSE m.away_score END AS goals_for,
+ CASE WHEN m.home_team_id = t.id THEN m.away_score ELSE m.home_score END AS goals_against,
+ CASE
+ WHEN m.home_score = m.away_score THEN 'D'
+ WHEN (m.home_team_id = t.id AND m.home_score > m.away_score)
+ OR (m.away_team_id = t.id AND m.away_score > m.home_score) THEN 'W'
+ ELSE 'L'
+ END AS result,
+ CASE
+ WHEN m.home_score = m.away_score THEN 1
+ WHEN (m.home_team_id = t.id AND m.home_score > m.away_score)
+ OR (m.away_team_id = t.id AND m.away_score > m.home_score) THEN 3
+ ELSE 0
+ END AS points_earned
+FROM teams t
+JOIN matches m ON m.competition_id = t.competition_id
+ AND m.status = 'completed'
+ AND (m.home_team_id = t.id OR m.away_team_id = t.id)
+JOIN teams ht ON ht.id = m.home_team_id
+JOIN teams at ON at.id = m.away_team_id;
diff --git a/supabase/migrations/20250524000003_rls.sql b/supabase/migrations/20250524000003_rls.sql
new file mode 100644
index 0000000..69b20cf
--- /dev/null
+++ b/supabase/migrations/20250524000003_rls.sql
@@ -0,0 +1,170 @@
+-- RLS helpers and policies
+
+ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
+ALTER TABLE leagues ENABLE ROW LEVEL SECURITY;
+ALTER TABLE league_rules ENABLE ROW LEVEL SECURITY;
+ALTER TABLE competitions ENABLE ROW LEVEL SECURITY;
+ALTER TABLE players ENABLE ROW LEVEL SECURITY;
+ALTER TABLE teams ENABLE ROW LEVEL SECURITY;
+ALTER TABLE team_members ENABLE ROW LEVEL SECURITY;
+ALTER TABLE team_availability ENABLE ROW LEVEL SECURITY;
+ALTER TABLE team_roster ENABLE ROW LEVEL SECURITY;
+ALTER TABLE roster_events ENABLE ROW LEVEL SECURITY;
+ALTER TABLE transfers ENABLE ROW LEVEL SECURITY;
+ALTER TABLE competition_league_managers ENABLE ROW LEVEL SECURITY;
+ALTER TABLE matches ENABLE ROW LEVEL SECURITY;
+ALTER TABLE match_signatures ENABLE ROW LEVEL SECURITY;
+ALTER TABLE match_result_submissions ENABLE ROW LEVEL SECURITY;
+ALTER TABLE match_player_stats ENABLE ROW LEVEL SECURITY;
+
+-- Helper: is competition participant
+CREATE OR REPLACE FUNCTION is_competition_participant(p_competition_id UUID)
+RETURNS BOOLEAN AS $$
+ SELECT EXISTS (
+ SELECT 1 FROM team_members tm
+ JOIN teams t ON t.id = tm.team_id
+ WHERE t.competition_id = p_competition_id AND tm.user_id = auth.uid()
+ )
+ OR EXISTS (
+ SELECT 1 FROM competition_league_managers
+ WHERE competition_id = p_competition_id AND user_id = auth.uid()
+ )
+ OR EXISTS (
+ SELECT 1 FROM competitions c
+ JOIN leagues l ON l.id = c.league_id
+ WHERE c.id = p_competition_id AND (c.created_by = auth.uid() OR l.created_by = auth.uid())
+ );
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+CREATE OR REPLACE FUNCTION is_league_organizer(p_league_id UUID)
+RETURNS BOOLEAN AS $$
+ SELECT EXISTS (
+ SELECT 1 FROM leagues WHERE id = p_league_id AND created_by = auth.uid()
+ );
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+CREATE OR REPLACE FUNCTION is_competition_league_manager(p_competition_id UUID)
+RETURNS BOOLEAN AS $$
+ SELECT EXISTS (
+ SELECT 1 FROM competition_league_managers
+ WHERE competition_id = p_competition_id AND user_id = auth.uid()
+ );
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+CREATE OR REPLACE FUNCTION is_team_manager(p_team_id UUID)
+RETURNS BOOLEAN AS $$
+ SELECT EXISTS (
+ SELECT 1 FROM team_members
+ WHERE team_id = p_team_id AND user_id = auth.uid() AND role = 'manager'
+ );
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+CREATE OR REPLACE FUNCTION is_team_captain_or_manager(p_team_id UUID)
+RETURNS BOOLEAN AS $$
+ SELECT EXISTS (
+ SELECT 1 FROM team_members
+ WHERE team_id = p_team_id AND user_id = auth.uid()
+ );
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+-- Profiles
+CREATE POLICY profiles_select ON profiles FOR SELECT TO authenticated USING (true);
+CREATE POLICY profiles_update ON profiles FOR UPDATE TO authenticated USING (id = auth.uid());
+
+-- Leagues
+CREATE POLICY leagues_select ON leagues FOR SELECT TO authenticated USING (true);
+CREATE POLICY leagues_insert ON leagues FOR INSERT TO authenticated WITH CHECK (created_by = auth.uid());
+CREATE POLICY leagues_update ON leagues FOR UPDATE TO authenticated USING (created_by = auth.uid());
+
+-- League rules
+CREATE POLICY league_rules_select ON league_rules FOR SELECT TO authenticated USING (true);
+CREATE POLICY league_rules_insert ON league_rules FOR INSERT TO authenticated
+ WITH CHECK (is_league_organizer(league_id));
+
+-- Competitions
+CREATE POLICY competitions_select ON competitions FOR SELECT TO authenticated
+ USING (is_competition_participant(id) OR is_league_organizer(league_id));
+CREATE POLICY competitions_insert ON competitions FOR INSERT TO authenticated
+ WITH CHECK (is_league_organizer(league_id));
+CREATE POLICY competitions_update ON competitions FOR UPDATE TO authenticated
+ USING (is_league_organizer(league_id));
+
+-- Players (global registry)
+CREATE POLICY players_select ON players FOR SELECT TO authenticated USING (true);
+CREATE POLICY players_insert ON players FOR INSERT TO authenticated WITH CHECK (true);
+CREATE POLICY players_update ON players FOR UPDATE TO authenticated USING (true);
+
+-- Teams
+CREATE POLICY teams_select ON teams FOR SELECT TO authenticated
+ USING (is_competition_participant(competition_id));
+CREATE POLICY teams_insert ON teams FOR INSERT TO authenticated
+ WITH CHECK (
+ EXISTS (
+ SELECT 1 FROM competitions c
+ WHERE c.id = competition_id AND is_league_organizer(c.league_id)
+ )
+ );
+CREATE POLICY teams_update ON teams FOR UPDATE TO authenticated
+ USING (is_team_manager(id) OR EXISTS (
+ SELECT 1 FROM competitions c WHERE c.id = competition_id AND is_league_organizer(c.league_id)
+ ));
+
+-- Team members
+CREATE POLICY team_members_select ON team_members FOR SELECT TO authenticated
+ USING (EXISTS (SELECT 1 FROM teams t WHERE t.id = team_id AND is_competition_participant(t.competition_id)));
+CREATE POLICY team_members_insert ON team_members FOR INSERT TO authenticated
+ WITH CHECK (EXISTS (
+ SELECT 1 FROM teams t JOIN competitions c ON c.id = t.competition_id
+ WHERE t.id = team_id AND is_league_organizer(c.league_id)
+ ));
+
+-- Team availability
+CREATE POLICY team_availability_all ON team_availability FOR ALL TO authenticated
+ USING (is_team_manager(team_id))
+ WITH CHECK (is_team_manager(team_id));
+
+-- Team roster / events / transfers - read for participants
+CREATE POLICY team_roster_select ON team_roster FOR SELECT TO authenticated
+ USING (is_competition_participant(competition_id));
+
+CREATE POLICY roster_events_select ON roster_events FOR SELECT TO authenticated
+ USING (is_competition_participant(competition_id));
+CREATE POLICY roster_events_insert ON roster_events FOR INSERT TO authenticated
+ WITH CHECK (is_team_manager(team_id));
+
+CREATE POLICY transfers_select ON transfers FOR SELECT TO authenticated
+ USING (is_competition_participant(competition_id));
+CREATE POLICY transfers_insert ON transfers FOR INSERT TO authenticated
+ WITH CHECK (is_team_manager(from_team_id));
+
+-- Competition league managers
+CREATE POLICY clm_select ON competition_league_managers FOR SELECT TO authenticated
+ USING (is_competition_participant(competition_id));
+CREATE POLICY clm_insert ON competition_league_managers FOR INSERT TO authenticated
+ WITH CHECK (EXISTS (
+ SELECT 1 FROM competitions c WHERE c.id = competition_id AND is_league_organizer(c.league_id)
+ ));
+
+-- Matches
+CREATE POLICY matches_select ON matches FOR SELECT TO authenticated
+ USING (is_competition_participant(competition_id));
+CREATE POLICY matches_update ON matches FOR UPDATE TO authenticated
+ USING (is_competition_league_manager(competition_id));
+
+-- Match signatures
+CREATE POLICY match_signatures_select ON match_signatures FOR SELECT TO authenticated
+ USING (EXISTS (SELECT 1 FROM matches m WHERE m.id = match_id AND is_competition_participant(m.competition_id)));
+CREATE POLICY match_signatures_insert ON match_signatures FOR INSERT TO authenticated
+ WITH CHECK (is_team_captain_or_manager(team_id));
+
+-- Result submissions
+CREATE POLICY result_submissions_select ON match_result_submissions FOR SELECT TO authenticated
+ USING (EXISTS (SELECT 1 FROM matches m WHERE m.id = match_id AND is_competition_participant(m.competition_id)));
+CREATE POLICY result_submissions_insert ON match_result_submissions FOR INSERT TO authenticated
+ WITH CHECK (is_team_captain_or_manager(team_id));
+
+-- Player stats
+CREATE POLICY match_player_stats_select ON match_player_stats FOR SELECT TO authenticated
+ USING (EXISTS (SELECT 1 FROM matches m WHERE m.id = match_id AND is_competition_participant(m.competition_id)));
+CREATE POLICY match_player_stats_insert ON match_player_stats FOR INSERT TO authenticated
+ WITH CHECK (is_team_captain_or_manager(team_id));
diff --git a/supabase/migrations/20250524000004_functions.sql b/supabase/migrations/20250524000004_functions.sql
new file mode 100644
index 0000000..6f21a78
--- /dev/null
+++ b/supabase/migrations/20250524000004_functions.sql
@@ -0,0 +1,302 @@
+-- Core business logic functions
+
+CREATE OR REPLACE FUNCTION get_default_rules()
+RETURNS JSONB AS $$
+ SELECT jsonb_build_object(
+ 'points_win', 3,
+ 'points_draw', 1,
+ 'round_robin_format', 'double',
+ 'transfer_policy', 'anytime',
+ 'auto_qualify_count', 1,
+ 'strict_availability', false,
+ 'result_approval_required', true,
+ 'cup_format', jsonb_build_object(
+ 'legs', 'single',
+ 'third_place_match', false,
+ 'seeding', 'random'
+ )
+ );
+$$ LANGUAGE sql IMMUTABLE;
+
+-- Snapshot rules when activating competition
+CREATE OR REPLACE FUNCTION activate_competition(p_competition_id UUID)
+RETURNS VOID AS $$
+DECLARE
+ v_league_id UUID;
+ v_latest_rules JSONB;
+ v_version INT;
+BEGIN
+ SELECT league_id INTO v_league_id FROM competitions WHERE id = p_competition_id;
+
+ SELECT rules, version INTO v_latest_rules, v_version
+ FROM league_rules
+ WHERE league_id = v_league_id
+ ORDER BY version DESC
+ LIMIT 1;
+
+ IF v_latest_rules IS NULL THEN
+ v_latest_rules := get_default_rules();
+ v_version := 1;
+ END IF;
+
+ UPDATE competitions
+ SET status = 'active',
+ rules_snapshot = v_latest_rules,
+ rule_set_version = v_version
+ WHERE id = p_competition_id AND status = 'draft';
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- Generate double round-robin fixtures
+CREATE OR REPLACE FUNCTION generate_league_fixtures(p_competition_id UUID)
+RETURNS INT AS $$
+DECLARE
+ team_ids UUID[];
+ n INT;
+ rounds INT;
+ r INT;
+ i INT;
+ j INT;
+ fixed UUID;
+ rotating UUID[];
+ match_count INT := 0;
+ leg INT;
+BEGIN
+ SELECT ARRAY_AGG(id ORDER BY name) INTO team_ids
+ FROM teams WHERE competition_id = p_competition_id;
+
+ n := COALESCE(array_length(team_ids, 1), 0);
+ IF n < 2 THEN
+ RAISE EXCEPTION 'Need at least 2 teams';
+ END IF;
+
+ DELETE FROM matches WHERE competition_id = p_competition_id AND status = 'scheduled';
+
+ IF n % 2 = 1 THEN
+ team_ids := team_ids || NULL::UUID;
+ n := n + 1;
+ END IF;
+
+ rounds := n - 1;
+ rotating := team_ids[2:n];
+
+ FOR leg IN 1..2 LOOP
+ FOR r IN 1..rounds LOOP
+ IF team_ids[1] IS NOT NULL AND rotating[1] IS NOT NULL THEN
+ IF leg = 1 THEN
+ INSERT INTO matches (competition_id, home_team_id, away_team_id, round, matchday, leg, status)
+ VALUES (p_competition_id, team_ids[1], rotating[1], r, r + (leg-1)*rounds, leg, 'scheduled');
+ ELSE
+ INSERT INTO matches (competition_id, home_team_id, away_team_id, round, matchday, leg, status)
+ VALUES (p_competition_id, rotating[1], team_ids[1], r, r + (leg-1)*rounds, leg, 'scheduled');
+ END IF;
+ match_count := match_count + 1;
+ END IF;
+
+ FOR i IN 1..(array_length(rotating, 1) / 2) LOOP
+ j := array_length(rotating, 1) - i + 1;
+ IF rotating[i] IS NOT NULL AND rotating[j] IS NOT NULL AND i <> j THEN
+ IF leg = 1 THEN
+ INSERT INTO matches (competition_id, home_team_id, away_team_id, round, matchday, leg, status)
+ VALUES (p_competition_id, rotating[i], rotating[j], r, r + (leg-1)*rounds, leg, 'scheduled');
+ ELSE
+ INSERT INTO matches (competition_id, home_team_id, away_team_id, round, matchday, leg, status)
+ VALUES (p_competition_id, rotating[j], rotating[i], r, r + (leg-1)*rounds, leg, 'scheduled');
+ END IF;
+ match_count := match_count + 1;
+ END IF;
+ END LOOP;
+
+ fixed := rotating[array_length(rotating, 1)];
+ rotating := ARRAY[fixed] || rotating[1:array_length(rotating,1)-1];
+ END LOOP;
+ END LOOP;
+
+ RETURN match_count;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- Generate cup bracket (single elimination, first round)
+CREATE OR REPLACE FUNCTION generate_cup_bracket(p_competition_id UUID)
+RETURNS INT AS $$
+DECLARE
+ team_ids UUID[];
+ n INT;
+ i INT;
+ match_count INT := 0;
+BEGIN
+ SELECT ARRAY_AGG(id ORDER BY COALESCE(cup_seed, 999), name) INTO team_ids
+ FROM teams WHERE competition_id = p_competition_id;
+
+ n := COALESCE(array_length(team_ids, 1), 0);
+ IF n < 2 THEN RAISE EXCEPTION 'Need at least 2 teams'; END IF;
+
+ DELETE FROM matches WHERE competition_id = p_competition_id AND status = 'scheduled';
+
+ i := 1;
+ WHILE i < n LOOP
+ IF team_ids[i] IS NOT NULL AND team_ids[i+1] IS NOT NULL THEN
+ INSERT INTO matches (competition_id, home_team_id, away_team_id, bracket_round, bracket_slot, status)
+ VALUES (p_competition_id, team_ids[i], team_ids[i+1], 1, (i+1)/2, 'scheduled');
+ match_count := match_count + 1;
+ END IF;
+ i := i + 2;
+ END LOOP;
+
+ RETURN match_count;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- Submit match result from team
+CREATE OR REPLACE FUNCTION submit_match_result(
+ p_match_id UUID,
+ p_team_id UUID,
+ p_home_score INT,
+ p_away_score INT
+)
+RETURNS VOID AS $$
+DECLARE
+ v_competition_id UUID;
+ v_sub_count INT;
+ v_home_sub INT;
+ v_away_sub INT;
+ v_sub1_home INT;
+ v_sub1_away INT;
+ v_sub2_home INT;
+ v_sub2_away INT;
+BEGIN
+ SELECT competition_id INTO v_competition_id FROM matches WHERE id = p_match_id;
+
+ INSERT INTO match_result_submissions (match_id, team_id, home_score, away_score, submitted_by)
+ VALUES (p_match_id, p_team_id, p_home_score, p_away_score, auth.uid())
+ ON CONFLICT (match_id, team_id) DO UPDATE
+ SET home_score = EXCLUDED.home_score, away_score = EXCLUDED.away_score,
+ submitted_at = now(), submitted_by = auth.uid();
+
+ SELECT COUNT(*) INTO v_sub_count FROM match_result_submissions WHERE match_id = p_match_id;
+
+ IF v_sub_count < 2 THEN
+ UPDATE matches SET result_status = 'result_submitted', status = 'awaiting_results'
+ WHERE id = p_match_id;
+ RETURN;
+ END IF;
+
+ SELECT home_score, away_score INTO v_sub1_home, v_sub1_away
+ FROM match_result_submissions WHERE match_id = p_match_id
+ ORDER BY submitted_at LIMIT 1;
+
+ SELECT home_score, away_score INTO v_sub2_home, v_sub2_away
+ FROM match_result_submissions WHERE match_id = p_match_id
+ ORDER BY submitted_at DESC LIMIT 1;
+
+ IF v_sub1_home = v_sub2_home AND v_sub1_away = v_sub2_away THEN
+ UPDATE matches SET result_status = 'pending_approval', status = 'pending_approval'
+ WHERE id = p_match_id;
+ ELSE
+ UPDATE matches SET result_status = 'disputed', status = 'disputed'
+ WHERE id = p_match_id;
+ END IF;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- League manager approves result
+CREATE OR REPLACE FUNCTION approve_match_result(p_match_id UUID)
+RETURNS VOID AS $$
+DECLARE
+ v_sub RECORD;
+BEGIN
+ IF NOT EXISTS (
+ SELECT 1 FROM matches m
+ WHERE m.id = p_match_id
+ AND is_competition_league_manager(m.competition_id)
+ ) AND NOT EXISTS (
+ SELECT 1 FROM matches m JOIN competitions c ON c.id = m.competition_id
+ JOIN leagues l ON l.id = c.league_id
+ WHERE m.id = p_match_id AND l.created_by = auth.uid()
+ ) THEN
+ RAISE EXCEPTION 'Not authorized';
+ END IF;
+
+ SELECT home_score, away_score INTO v_sub
+ FROM match_result_submissions WHERE match_id = p_match_id LIMIT 1;
+
+ UPDATE matches SET
+ home_score = v_sub.home_score,
+ away_score = v_sub.away_score,
+ status = 'completed',
+ result_status = 'completed',
+ approved_by = auth.uid(),
+ approved_at = now()
+ WHERE id = p_match_id;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- League manager sets result directly
+CREATE OR REPLACE FUNCTION set_match_result_by_manager(
+ p_match_id UUID,
+ p_home_score INT,
+ p_away_score INT,
+ p_note TEXT DEFAULT NULL
+)
+RETURNS VOID AS $$
+BEGIN
+ IF NOT EXISTS (
+ SELECT 1 FROM matches m WHERE m.id = p_match_id
+ AND is_competition_league_manager(m.competition_id)
+ ) AND NOT EXISTS (
+ SELECT 1 FROM matches m JOIN competitions c ON c.id = m.competition_id
+ JOIN leagues l ON l.id = c.league_id
+ WHERE m.id = p_match_id AND l.created_by = auth.uid()
+ ) THEN
+ RAISE EXCEPTION 'Not authorized';
+ END IF;
+
+ UPDATE matches SET
+ home_score = p_home_score,
+ away_score = p_away_score,
+ status = 'completed',
+ result_status = 'completed',
+ approved_by = auth.uid(),
+ approved_at = now(),
+ resolution_note = p_note
+ WHERE id = p_match_id;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- Sign schedule
+CREATE OR REPLACE FUNCTION sign_match_schedule(p_match_id UUID, p_team_id UUID)
+RETURNS VOID AS $$
+DECLARE
+ v_sig_count INT;
+ v_proposed TIMESTAMPTZ;
+BEGIN
+ SELECT proposed_scheduled_at INTO v_proposed FROM matches WHERE id = p_match_id;
+
+ INSERT INTO match_signatures (match_id, team_id, user_id, signature_type)
+ VALUES (p_match_id, p_team_id, auth.uid(), 'schedule')
+ ON CONFLICT (match_id, team_id, signature_type) DO NOTHING;
+
+ SELECT COUNT(*) INTO v_sig_count FROM match_signatures
+ WHERE match_id = p_match_id AND signature_type = 'schedule';
+
+ IF v_sig_count >= 2 AND v_proposed IS NOT NULL THEN
+ UPDATE matches SET
+ status = 'schedule_confirmed',
+ scheduled_at = v_proposed,
+ venue = (SELECT home_stadium_name FROM teams t
+ JOIN matches m ON m.home_team_id = t.id WHERE m.id = p_match_id)
+ WHERE id = p_match_id;
+ END IF;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- Propose schedule time
+CREATE OR REPLACE FUNCTION propose_match_schedule(p_match_id UUID, p_scheduled_at TIMESTAMPTZ)
+RETURNS VOID AS $$
+BEGIN
+ UPDATE matches SET
+ proposed_scheduled_at = p_scheduled_at,
+ status = 'schedule_pending'
+ WHERE id = p_match_id;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
diff --git a/supabase/migrations/20250524000005_storage.sql b/supabase/migrations/20250524000005_storage.sql
new file mode 100644
index 0000000..bc470b0
--- /dev/null
+++ b/supabase/migrations/20250524000005_storage.sql
@@ -0,0 +1,15 @@
+-- Team logos storage bucket
+INSERT INTO storage.buckets (id, name, public)
+VALUES ('team-logos', 'team-logos', true)
+ON CONFLICT (id) DO NOTHING;
+
+CREATE POLICY team_logos_public_read ON storage.objects
+ FOR SELECT USING (bucket_id = 'team-logos');
+
+CREATE POLICY team_logos_authenticated_upload ON storage.objects
+ FOR INSERT TO authenticated
+ WITH CHECK (bucket_id = 'team-logos');
+
+CREATE POLICY team_logos_authenticated_update ON storage.objects
+ FOR UPDATE TO authenticated
+ USING (bucket_id = 'team-logos');
diff --git a/supabase/migrations/20250524000006_portal_roles.sql b/supabase/migrations/20250524000006_portal_roles.sql
new file mode 100644
index 0000000..2d51ebd
--- /dev/null
+++ b/supabase/migrations/20250524000006_portal_roles.sql
@@ -0,0 +1,195 @@
+-- Portal roles, league masters, team extras, support issues
+
+CREATE TYPE portal_role AS ENUM ('league_master', 'manager');
+
+ALTER TABLE profiles
+ ADD COLUMN IF NOT EXISTS portal_role portal_role NOT NULL DEFAULT 'manager';
+
+ALTER TABLE teams
+ ADD COLUMN IF NOT EXISTS nickname TEXT,
+ ADD COLUMN IF NOT EXISTS icon TEXT NOT NULL DEFAULT 'shield';
+
+CREATE TABLE IF NOT EXISTS league_masters (
+ league_id UUID NOT NULL REFERENCES leagues(id) ON DELETE CASCADE,
+ user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
+ assigned_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ PRIMARY KEY (league_id, user_id)
+);
+
+CREATE TABLE IF NOT EXISTS support_issues (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ league_id UUID NOT NULL REFERENCES leagues(id) ON DELETE CASCADE,
+ competition_id UUID REFERENCES competitions(id) ON DELETE SET NULL,
+ submitted_by UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
+ subject TEXT NOT NULL,
+ body TEXT NOT NULL,
+ status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open', 'in_progress', 'resolved')),
+ master_reply TEXT,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+CREATE TRIGGER support_issues_updated_at
+ BEFORE UPDATE ON support_issues
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at();
+
+-- Helpers
+CREATE OR REPLACE FUNCTION is_global_league_master()
+RETURNS BOOLEAN AS $$
+ SELECT EXISTS (
+ SELECT 1 FROM profiles WHERE id = auth.uid() AND portal_role = 'league_master'
+ );
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+CREATE OR REPLACE FUNCTION is_league_master(p_league_id UUID)
+RETURNS BOOLEAN AS $$
+ SELECT is_global_league_master()
+ OR EXISTS (SELECT 1 FROM leagues WHERE id = p_league_id AND created_by = auth.uid())
+ OR EXISTS (
+ SELECT 1 FROM league_masters WHERE league_id = p_league_id AND user_id = auth.uid()
+ );
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+-- Extend organizer check to include assigned masters
+CREATE OR REPLACE FUNCTION is_league_organizer(p_league_id UUID)
+RETURNS BOOLEAN AS $$
+ SELECT is_league_master(p_league_id);
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
+
+-- Profile trigger: portal role from signup metadata
+CREATE OR REPLACE FUNCTION handle_new_user()
+RETURNS TRIGGER AS $$
+DECLARE
+ v_role portal_role;
+BEGIN
+ BEGIN
+ v_role := COALESCE(
+ (NEW.raw_user_meta_data->>'portal_role')::portal_role,
+ 'manager'::portal_role
+ );
+ EXCEPTION WHEN OTHERS THEN
+ v_role := 'manager';
+ END;
+
+ INSERT INTO public.profiles (id, display_name, portal_role)
+ VALUES (
+ NEW.id,
+ COALESCE(NEW.raw_user_meta_data->>'display_name', split_part(NEW.email, '@', 1)),
+ v_role
+ )
+ ON CONFLICT (id) DO UPDATE SET
+ display_name = COALESCE(EXCLUDED.display_name, profiles.display_name),
+ portal_role = COALESCE(EXCLUDED.portal_role, profiles.portal_role);
+
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+-- RLS new tables
+ALTER TABLE league_masters ENABLE ROW LEVEL SECURITY;
+ALTER TABLE support_issues ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY league_masters_select ON league_masters FOR SELECT TO authenticated
+ USING (is_league_master(league_id) OR user_id = auth.uid());
+
+CREATE POLICY league_masters_insert ON league_masters FOR INSERT TO authenticated
+ WITH CHECK (is_league_master(league_id));
+
+CREATE POLICY league_masters_delete ON league_masters FOR DELETE TO authenticated
+ USING (is_league_master(league_id));
+
+CREATE POLICY support_issues_select ON support_issues FOR SELECT TO authenticated
+ USING (
+ submitted_by = auth.uid()
+ OR is_league_master(league_id)
+ );
+
+CREATE POLICY support_issues_insert ON support_issues FOR INSERT TO authenticated
+ WITH CHECK (submitted_by = auth.uid());
+
+CREATE POLICY support_issues_update ON support_issues FOR UPDATE TO authenticated
+ USING (is_league_master(league_id));
+
+-- League delete (masters only)
+CREATE POLICY leagues_delete ON leagues FOR DELETE TO authenticated
+ USING (is_league_master(id));
+
+-- Team delete in draft competitions
+CREATE POLICY teams_delete ON teams FOR DELETE TO authenticated
+ USING (
+ EXISTS (
+ SELECT 1 FROM competitions c
+ WHERE c.id = competition_id
+ AND c.status = 'draft'
+ AND is_league_master(c.league_id)
+ )
+ );
+
+-- Recreate standings view with nickname/icon (must DROP first: REPLACE cannot reorder columns)
+DROP VIEW IF EXISTS competition_standings;
+CREATE VIEW competition_standings AS
+SELECT
+ t.competition_id,
+ t.id AS team_id,
+ t.name AS team_name,
+ t.nickname AS team_nickname,
+ t.icon AS team_icon,
+ t.logo_path,
+ COUNT(m.id) FILTER (WHERE m.status = 'completed') AS played,
+ COUNT(m.id) FILTER (
+ WHERE m.status = 'completed'
+ AND (
+ (m.home_team_id = t.id AND m.home_score > m.away_score)
+ OR (m.away_team_id = t.id AND m.away_score > m.home_score)
+ )
+ ) AS won,
+ COUNT(m.id) FILTER (
+ WHERE m.status = 'completed' AND m.home_score = m.away_score
+ ) AS drawn,
+ COUNT(m.id) FILTER (
+ WHERE m.status = 'completed'
+ AND (
+ (m.home_team_id = t.id AND m.home_score < m.away_score)
+ OR (m.away_team_id = t.id AND m.away_score < m.home_score)
+ )
+ ) AS lost,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status = 'completed' AND m.home_team_id = t.id THEN m.home_score
+ WHEN m.status = 'completed' AND m.away_team_id = t.id THEN m.away_score
+ ELSE 0
+ END
+ ), 0)::INT AS goals_for,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status = 'completed' AND m.home_team_id = t.id THEN m.away_score
+ WHEN m.status = 'completed' AND m.away_team_id = t.id THEN m.home_score
+ ELSE 0
+ END
+ ), 0)::INT AS goals_against,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status = 'completed' AND m.home_team_id = t.id THEN m.home_score - m.away_score
+ WHEN m.status = 'completed' AND m.away_team_id = t.id THEN m.away_score - m.home_score
+ ELSE 0
+ END
+ ), 0)::INT AS goal_difference,
+ COALESCE(SUM(
+ CASE
+ WHEN m.status <> 'completed' THEN 0
+ WHEN m.home_score = m.away_score THEN 1
+ WHEN m.home_team_id = t.id AND m.home_score > m.away_score THEN 3
+ WHEN m.away_team_id = t.id AND m.away_score > m.home_score THEN 3
+ ELSE 0
+ END
+ ), 0)::INT AS points
+FROM teams t
+LEFT JOIN matches m ON m.competition_id = t.competition_id
+ AND (m.home_team_id = t.id OR m.away_team_id = t.id)
+GROUP BY t.competition_id, t.id, t.name, t.nickname, t.icon, t.logo_path;
+
+CREATE OR REPLACE FUNCTION get_user_id_by_email(p_email TEXT)
+RETURNS UUID AS $$
+ SELECT id FROM auth.users WHERE email = lower(trim(p_email)) LIMIT 1;
+$$ LANGUAGE sql SECURITY DEFINER STABLE;
diff --git a/supabase/migrations/20250524000007_profile_sync.sql b/supabase/migrations/20250524000007_profile_sync.sql
new file mode 100644
index 0000000..2f0c2c1
--- /dev/null
+++ b/supabase/migrations/20250524000007_profile_sync.sql
@@ -0,0 +1,53 @@
+-- Profile sync RPC + insert policy (safe if 006 already applied)
+
+DO $$ BEGIN
+ CREATE TYPE portal_role AS ENUM ('league_master', 'manager');
+EXCEPTION
+ WHEN duplicate_object THEN NULL;
+END $$;
+
+ALTER TABLE profiles
+ ADD COLUMN IF NOT EXISTS portal_role portal_role NOT NULL DEFAULT 'manager';
+
+-- Backfill portal_role from signup metadata
+UPDATE profiles p
+SET portal_role = (u.raw_user_meta_data->>'portal_role')::portal_role
+FROM auth.users u
+WHERE u.id = p.id
+ AND u.raw_user_meta_data->>'portal_role' IN ('league_master', 'manager');
+
+CREATE OR REPLACE FUNCTION ensure_user_profile(
+ p_display_name TEXT DEFAULT NULL,
+ p_portal_role portal_role DEFAULT 'manager'
+)
+RETURNS void
+LANGUAGE plpgsql
+SECURITY DEFINER
+SET search_path = public
+AS $$
+BEGIN
+ IF auth.uid() IS NULL THEN
+ RAISE EXCEPTION 'Not authenticated';
+ END IF;
+
+ INSERT INTO public.profiles (id, display_name, portal_role)
+ VALUES (
+ auth.uid(),
+ COALESCE(
+ p_display_name,
+ (SELECT COALESCE(raw_user_meta_data->>'display_name', email) FROM auth.users WHERE id = auth.uid())
+ ),
+ p_portal_role
+ )
+ ON CONFLICT (id) DO UPDATE SET
+ display_name = COALESCE(EXCLUDED.display_name, profiles.display_name),
+ portal_role = COALESCE(EXCLUDED.portal_role, profiles.portal_role);
+END;
+$$;
+
+GRANT EXECUTE ON FUNCTION ensure_user_profile(TEXT, portal_role) TO authenticated;
+
+DROP POLICY IF EXISTS profiles_insert_own ON profiles;
+CREATE POLICY profiles_insert_own ON profiles
+ FOR INSERT TO authenticated
+ WITH CHECK (id = auth.uid());
diff --git a/supabase/migrations/20250524000008_fix_signup_trigger.sql b/supabase/migrations/20250524000008_fix_signup_trigger.sql
new file mode 100644
index 0000000..8e6cdbf
--- /dev/null
+++ b/supabase/migrations/20250524000008_fix_signup_trigger.sql
@@ -0,0 +1,53 @@
+-- Fix auth signup 500 ("Database error saving new user") from profile trigger failures
+
+DO $$ BEGIN
+ CREATE TYPE portal_role AS ENUM ('league_master', 'manager');
+EXCEPTION
+ WHEN duplicate_object THEN NULL;
+END $$;
+
+ALTER TABLE public.profiles
+ ADD COLUMN IF NOT EXISTS portal_role portal_role NOT NULL DEFAULT 'manager';
+
+CREATE OR REPLACE FUNCTION public.handle_new_user()
+RETURNS TRIGGER
+LANGUAGE plpgsql
+SECURITY DEFINER
+SET search_path = public
+AS $$
+DECLARE
+ v_role portal_role := 'manager';
+ v_name TEXT;
+BEGIN
+ v_name := COALESCE(
+ NULLIF(trim(NEW.raw_user_meta_data->>'display_name'), ''),
+ split_part(COALESCE(NEW.email, 'user'), '@', 1)
+ );
+
+ IF NEW.raw_user_meta_data IS NOT NULL
+ AND (NEW.raw_user_meta_data->>'portal_role') IN ('league_master', 'manager') THEN
+ v_role := (NEW.raw_user_meta_data->>'portal_role')::portal_role;
+ END IF;
+
+ INSERT INTO public.profiles (id, display_name, portal_role)
+ VALUES (NEW.id, v_name, v_role)
+ ON CONFLICT (id) DO UPDATE SET
+ display_name = COALESCE(EXCLUDED.display_name, profiles.display_name),
+ portal_role = COALESCE(EXCLUDED.portal_role, profiles.portal_role);
+
+ RETURN NEW;
+EXCEPTION
+ WHEN undefined_column THEN
+ -- DB missing portal_role — minimal profile so signup still succeeds
+ INSERT INTO public.profiles (id, display_name)
+ VALUES (NEW.id, v_name)
+ ON CONFLICT (id) DO UPDATE SET
+ display_name = COALESCE(EXCLUDED.display_name, profiles.display_name);
+ RETURN NEW;
+ WHEN OTHERS THEN
+ RAISE WARNING 'handle_new_user failed for user %: %', NEW.id, SQLERRM;
+ RETURN NEW;
+END;
+$$;
+
+GRANT EXECUTE ON FUNCTION public.handle_new_user() TO postgres, service_role;
diff --git a/supabase/scripts/fix-manager-account.sql b/supabase/scripts/fix-manager-account.sql
new file mode 100644
index 0000000..d05b166
--- /dev/null
+++ b/supabase/scripts/fix-manager-account.sql
@@ -0,0 +1,22 @@
+-- Run in Supabase SQL Editor if manager login fails with portal_role 400
+-- Replace USER_ID with your auth user id (from the error URL id=eq....)
+
+-- 1) Ensure column exists (or run: npm run db:push)
+-- 2) Set role for your account:
+
+UPDATE profiles
+SET portal_role = 'manager'
+WHERE id = 'b8d56b32-d492-4f8b-853c-1a5526ef475e';
+
+-- If no profile row exists:
+INSERT INTO profiles (id, display_name, portal_role)
+SELECT
+ id,
+ COALESCE(raw_user_meta_data->>'display_name', split_part(email, '@', 1)),
+ COALESCE(
+ (raw_user_meta_data->>'portal_role')::portal_role,
+ 'manager'::portal_role
+ )
+FROM auth.users
+WHERE id = 'b8d56b32-d492-4f8b-853c-1a5526ef475e'
+ON CONFLICT (id) DO UPDATE SET portal_role = EXCLUDED.portal_role;
diff --git a/supabase/scripts/fix-signup-trigger.sql b/supabase/scripts/fix-signup-trigger.sql
new file mode 100644
index 0000000..72a104c
--- /dev/null
+++ b/supabase/scripts/fix-signup-trigger.sql
@@ -0,0 +1,51 @@
+-- Run in Supabase SQL Editor if signup returns 500 / "Database error saving new user"
+-- (Same as migration 20250524000008_fix_signup_trigger.sql)
+
+DO $$ BEGIN
+ CREATE TYPE portal_role AS ENUM ('league_master', 'manager');
+EXCEPTION
+ WHEN duplicate_object THEN NULL;
+END $$;
+
+ALTER TABLE public.profiles
+ ADD COLUMN IF NOT EXISTS portal_role portal_role NOT NULL DEFAULT 'manager';
+
+CREATE OR REPLACE FUNCTION public.handle_new_user()
+RETURNS TRIGGER
+LANGUAGE plpgsql
+SECURITY DEFINER
+SET search_path = public
+AS $$
+DECLARE
+ v_role portal_role := 'manager';
+ v_name TEXT;
+BEGIN
+ v_name := COALESCE(
+ NULLIF(trim(NEW.raw_user_meta_data->>'display_name'), ''),
+ split_part(COALESCE(NEW.email, 'user'), '@', 1)
+ );
+
+ IF NEW.raw_user_meta_data IS NOT NULL
+ AND (NEW.raw_user_meta_data->>'portal_role') IN ('league_master', 'manager') THEN
+ v_role := (NEW.raw_user_meta_data->>'portal_role')::portal_role;
+ END IF;
+
+ INSERT INTO public.profiles (id, display_name, portal_role)
+ VALUES (NEW.id, v_name, v_role)
+ ON CONFLICT (id) DO UPDATE SET
+ display_name = COALESCE(EXCLUDED.display_name, profiles.display_name),
+ portal_role = COALESCE(EXCLUDED.portal_role, profiles.portal_role);
+
+ RETURN NEW;
+EXCEPTION
+ WHEN undefined_column THEN
+ INSERT INTO public.profiles (id, display_name)
+ VALUES (NEW.id, v_name)
+ ON CONFLICT (id) DO UPDATE SET
+ display_name = COALESCE(EXCLUDED.display_name, profiles.display_name);
+ RETURN NEW;
+ WHEN OTHERS THEN
+ RAISE WARNING 'handle_new_user failed for user %: %', NEW.id, SQLERRM;
+ RETURN NEW;
+END;
+$$;
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..42f1dd0
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [{ "name": "next" }],
+ "paths": { "@/*": ["./*"] }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/wrangler.jsonc b/wrangler.jsonc
new file mode 100644
index 0000000..044bf3a
--- /dev/null
+++ b/wrangler.jsonc
@@ -0,0 +1,20 @@
+{
+ "$schema": "node_modules/wrangler/config-schema.json",
+ "name": "yaltopia-fifa",
+ "main": ".open-next/worker.js",
+ "compatibility_date": "2024-12-30",
+ "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
+ "assets": {
+ "directory": ".open-next/assets",
+ "binding": "ASSETS"
+ },
+ "services": [
+ {
+ "binding": "WORKER_SELF_REFERENCE",
+ "service": "yaltopia-fifa"
+ }
+ ],
+ "images": {
+ "binding": "IMAGES"
+ }
+}