diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2354f2e..020246e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -13,12 +13,12 @@ { "label": "dev", "type": "shell", - "command": "./node_modules/.bin/dotenv -e .dev.env -e .public.env -e .secret.env -- 'turbo run dev --filter=${input:project}-frontend --filter=${input:project}-backend'" + "command": "./node_modules/.bin/dotenv -e .dev.env -e .secret.env -e .public.env -- 'turbo run dev --filter=${input:project}-frontend --filter=${input:project}-backend'", }, { "label": "serve", "type": "shell", - "command": "./node_modules/.bin/dotenv -e .public.env -e .secret.env -- 'turbo run serve --filter=${input:project}-frontend --filter=${input:project}-backend'" + "command": "./node_modules/.bin/dotenv -e .secret.env -e .public.env -- 'turbo run serve --filter=${input:project}-frontend --filter=${input:project}-backend'" }, { "label": "deploy", @@ -42,7 +42,7 @@ "id": "project", "description": "Full Stack Projects worth running", "type": "pickString", - "options": ["template", "test"] + "options": ["template", "test", "playoff-schedule"] }, { "id": "workspace", diff --git a/apps/playoff-schedule/backend/Dockerfile b/apps/playoff-schedule/backend/Dockerfile new file mode 100644 index 0000000..7f398e6 --- /dev/null +++ b/apps/playoff-schedule/backend/Dockerfile @@ -0,0 +1,5 @@ +FROM node:20-alpine +WORKDIR /usr/src/app +COPY ./dist /usr/src/app +EXPOSE 4590 +CMD ["node","bundle.js"] \ No newline at end of file diff --git a/apps/playoff-schedule/backend/build.ts b/apps/playoff-schedule/backend/build.ts new file mode 100644 index 0000000..3802a64 --- /dev/null +++ b/apps/playoff-schedule/backend/build.ts @@ -0,0 +1,37 @@ +// בס"ד +import { build, context } from "esbuild"; +import { spawn } from "child_process"; + +const isDev = process.env.NODE_ENV === "DEV"; + +const bundlePath = "dist/bundle.js"; + +const buildSettings = { + entryPoints: ["src/main.ts"], + outfile: "dist/bundle.js", + bundle: true, + plugins: [], + minify: true, + platform: "node", + target: ["ES2022"], + format: "cjs", + external: ["@repo/config-env"], +} satisfies Parameters[0]; + +const buildDev = async () => + context(buildSettings) + .then(async (ctx) => ctx.watch()) + .then(() => { + console.log("Starting nodemon to manage execution of bundle.js"); + spawn( + "nodemon", + [bundlePath, "--watch", bundlePath, "--ext", "js", "--exec", "node"], + { stdio: "inherit", shell: true } + ); + }); + +const buildedProject = isDev ? buildDev() : build(buildSettings); + +buildedProject.catch((error: unknown) => { + console.warn(error); +}); diff --git a/apps/playoff-schedule/backend/docker-compose.yml b/apps/playoff-schedule/backend/docker-compose.yml new file mode 100644 index 0000000..dc82686 --- /dev/null +++ b/apps/playoff-schedule/backend/docker-compose.yml @@ -0,0 +1,11 @@ +services: + backend: + build: + context: . + dockerfile: Dockerfile + + env_file: + - ../../../.public.env + - ../../../.secret.env + ports: + - "${BACKEND_PORT}:4590" # Maps host:${FRONTEND_PORT} to container:4590 diff --git a/apps/playoff-schedule/backend/package.json b/apps/playoff-schedule/backend/package.json new file mode 100644 index 0000000..6d29169 --- /dev/null +++ b/apps/playoff-schedule/backend/package.json @@ -0,0 +1,20 @@ +{ + "name": "playoff-schedule-backend", + "version": "1.0.0", + "description": "Backend for the application", + "main": "index.js", + "scripts": { + "test": "echo Backend Test Succeeded && exit 0", + "build": "tsx build.ts", + "serve": "node dist/bundle.js", + "dev": "tsx build.ts" + }, + "author": "", + "license": "ISC", + "dependencies": { + "process": "^0.11.10" + }, + "devDependencies": { + "@types/node": "^24.8.1" + } +} diff --git a/apps/playoff-schedule/backend/src/main.ts b/apps/playoff-schedule/backend/src/main.ts new file mode 100644 index 0000000..8b9058c --- /dev/null +++ b/apps/playoff-schedule/backend/src/main.ts @@ -0,0 +1,29 @@ +// בס"ד +import express from "express"; +import { apiRouter } from "./routes"; +import cors from "cors"; +import dotenv from "dotenv"; +dotenv.config(); + +const app = express(); +app.use( + cors({ + origin: "*", + }) +); +app.use("/api/v1", apiRouter); + +const defaultPort = 4590; +const port = process.env.BACKEND_PORT ?? defaultPort; + +app.use(express.json({ limit: "10mb" })); +app.use(express.urlencoded({ limit: "10mb", extended: true })); + +const apiKey: string | undefined = process.env.TBA_API_KEY; +if (apiKey === undefined) { + throw new Error("TBA_API_KEY is not defined."); +} + +app.listen(port, () => { + console.log(`Production server running at http://localhost:${port}`); +}); diff --git a/apps/playoff-schedule/backend/src/routes/index.ts b/apps/playoff-schedule/backend/src/routes/index.ts new file mode 100644 index 0000000..a7c0f29 --- /dev/null +++ b/apps/playoff-schedule/backend/src/routes/index.ts @@ -0,0 +1,12 @@ +// בס"ד +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { tbaRouter } from "./tba"; + +export const apiRouter = Router(); + +apiRouter.get("/health", (req, res) => { + res.status(StatusCodes.OK).send({ message: "Healthy!" }); +}); + +apiRouter.use("/tba", tbaRouter); \ No newline at end of file diff --git a/apps/playoff-schedule/backend/src/routes/tba.ts b/apps/playoff-schedule/backend/src/routes/tba.ts new file mode 100644 index 0000000..4e918e6 --- /dev/null +++ b/apps/playoff-schedule/backend/src/routes/tba.ts @@ -0,0 +1,35 @@ +// בס"ד +import { Router, type Request, type Response } from "express"; +import { StatusCodes } from "http-status-codes"; +import { fetchTba } from "../utils/tbaClient"; + +export const tbaRouter = Router(); + +const createTbaHandler = (name: string, suffix?: string) => + async (req: Request, res: Response): Promise => { + try { + const path = `/event/${req.params.eventKey}/${name}${suffix ? `/${suffix}` : ''}`; + const data = await fetchTba(path); + res.status(StatusCodes.OK).json(data); + } catch (error) { + console.error("Error in tba handler:", error); + res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .json({ error: "Failed to fetch data" }); + } + }; + +tbaRouter.get( + "/events/:eventKey/teams", + createTbaHandler("teams", "simple") +); + +tbaRouter.get( + "/events/:eventKey/matches", + createTbaHandler("matches", "simple") +); + +tbaRouter.get( + "/events/:eventKey/rankings", + createTbaHandler("rankings") +); diff --git a/apps/playoff-schedule/backend/src/utils/tbaClient.ts b/apps/playoff-schedule/backend/src/utils/tbaClient.ts new file mode 100644 index 0000000..7fa5d9d --- /dev/null +++ b/apps/playoff-schedule/backend/src/utils/tbaClient.ts @@ -0,0 +1,26 @@ +// Shared TBA fetcher to avoid duplicating auth + headers +const TBA_API_BASE = "https://www.thebluealliance.com/api/v3"; + +const getApiKey = (): string => { + const key = process.env.TBA_API_KEY; + if (!key) { + throw new Error("Missing TBA_API_KEY in environment variables"); + } + return key; +}; + +export const fetchTba = async (path: string): Promise => { + const response = await fetch(TBA_API_BASE + path, { + method: "GET", + headers: { + "X-TBA-Auth-Key": getApiKey(), + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error(`HTTP error, status: ${response.status}`); + } + + return response.json() as Promise; +}; diff --git a/apps/playoff-schedule/backend/src/vite-env.d.ts b/apps/playoff-schedule/backend/src/vite-env.d.ts new file mode 100644 index 0000000..ae59725 --- /dev/null +++ b/apps/playoff-schedule/backend/src/vite-env.d.ts @@ -0,0 +1,2 @@ +// בס"ד +/// diff --git a/apps/playoff-schedule/backend/turbo.json b/apps/playoff-schedule/backend/turbo.json new file mode 100644 index 0000000..52e8c76 --- /dev/null +++ b/apps/playoff-schedule/backend/turbo.json @@ -0,0 +1,12 @@ +{ + "extends": [ + "//" + ], + "tasks": { + "build": { + "outputs": [ + "dist/**" + ] + } + } +} diff --git a/apps/playoff-schedule/frontend/Dockerfile b/apps/playoff-schedule/frontend/Dockerfile new file mode 100644 index 0000000..d625b35 --- /dev/null +++ b/apps/playoff-schedule/frontend/Dockerfile @@ -0,0 +1,7 @@ +FROM node:20-alpine +WORKDIR /app +COPY ./start.ts /app/start.ts +COPY ./dist /app/dist +EXPOSE 443 +RUN ["npm","install","express"] +CMD ["npm","exec","--","tsx","start.ts"] \ No newline at end of file diff --git a/apps/playoff-schedule/frontend/docker-compose.yml b/apps/playoff-schedule/frontend/docker-compose.yml new file mode 100644 index 0000000..a27c44f --- /dev/null +++ b/apps/playoff-schedule/frontend/docker-compose.yml @@ -0,0 +1,11 @@ +services: + frontend: + build: + context: . + dockerfile: Dockerfile + + env_file: + - ../../../.public.env + - ../../../.secret.env + ports: + - "${FRONTEND_PORT}:443" # Maps host:${FRONTEND_PORT} to container:443 diff --git a/apps/playoff-schedule/frontend/index.html b/apps/playoff-schedule/frontend/index.html new file mode 100644 index 0000000..de79403 --- /dev/null +++ b/apps/playoff-schedule/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + GreenBlitz 4590 + + +
+ + + diff --git a/apps/playoff-schedule/frontend/package.json b/apps/playoff-schedule/frontend/package.json new file mode 100644 index 0000000..f9c8ee5 --- /dev/null +++ b/apps/playoff-schedule/frontend/package.json @@ -0,0 +1,32 @@ +{ + "name": "playoff-schedule-frontend", + "version": "1.0.0", + "description": "Frontend for the application", + "main": "index.js", + "scripts": { + "test": "echo Frontend Test Succeeded && exit 0", + "dev": "vite", + "build": "tsc -b && vite build", + "serve": "tsx start.ts", + "lint": "eslint .", + "preview": "vite preview" + }, + "author": "", + "license": "ISC", + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1", + "tailwindcss": "^4.1.16", + "@tailwindcss/vite": "^4.1.16" + }, + "devDependencies": { + "@eslint/js": "^9.36.0", + "@types/node": "^24.6.0", + "@types/react": "^19.1.16", + "@types/react-dom": "^19.1.9", + "@vitejs/plugin-react": "^5.0.4", + "babel-plugin-react-compiler": "^19.1.0-rc.3", + "globals": "^16.4.0", + "vite": "^7.1.7" + } +} diff --git a/apps/playoff-schedule/frontend/src/App.tsx b/apps/playoff-schedule/frontend/src/App.tsx new file mode 100644 index 0000000..d6d803d --- /dev/null +++ b/apps/playoff-schedule/frontend/src/App.tsx @@ -0,0 +1,96 @@ +// בס"ד +import type React from "react"; +import { useState, useMemo } from "react"; +import useLocalStorage from "./Hooks/LocalStorageHook"; +import { useEventData } from "./Hooks/useEventData"; +import { useMatchProcessing } from "./Hooks/useMatchProcessing"; +import { Header } from "./components/Header"; +import { EventInfoBar } from "./components/EventInfoBar"; +import { CurrentMatchStatus } from "./components/CurrentMatchStatus"; +import { SectionTitle } from "./components/SectionTitle"; +import { FinalResults } from "./components/FinalResults"; +import { MatchCard } from "./components/MatchCard"; +import { EmptyState } from "./components/EmptyState"; +import { noGap } from "./config/frcConfig"; + +const App: React.FC = () => { + const [activeEventKey, setActiveEventKey] = useLocalStorage( + "dashboard_active_event", + "" + ); + const [inputEventKey, setInputEventKey] = useState(activeEventKey); + + const { teams, allMatches, teamRank, searchStatus, performSearch } = + useEventData(activeEventKey, setActiveEventKey); + + const { + currentGlobalMatch, + targetTeamMatches, + futureMatches, + isEventOver, + isTeamDone, + isFutureEvent, + } = useMatchProcessing(allMatches); + + const teamNameMap = useMemo(() => { + const record: Record = {}; + teams.forEach((team) => { + record[team.key] = team.nickname; + }); + return record; + }, [teams]); + + const handleSearchSubmit = (event: React.FormEvent) => { + event.preventDefault(); + const formattedKey = inputEventKey.trim().toLowerCase(); + void performSearch(formattedKey); + }; + + return ( +
+
+ +
+ {searchStatus === "success" && ( + <> + + + + + + + {isEventOver ? ( + + ) : ( + <> + {targetTeamMatches.length === noGap && ( + + )} + + {targetTeamMatches.map((match) => ( + + ))} + + )} + + )} +
+
+ ); +}; + +export default App; diff --git a/apps/playoff-schedule/frontend/src/AppCss.css b/apps/playoff-schedule/frontend/src/AppCss.css new file mode 100644 index 0000000..24623f9 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/AppCss.css @@ -0,0 +1,278 @@ +:root { + --color-neutral-bg: #f5f5f5; + --color-header-bg: #263238; + --color-card-bg: #ffffff; + --color-text-main: #333333; + --color-text-sub: #666666; + --color-red-bg: #ffebee; + --color-red-border: #ef5350; + --color-red-text: #c62828; + --color-blue-bg: #e3f2fd; + --color-blue-border: #42a5f5; + --color-blue-text: #1565c0; + --color-accent: #ffa000; + --color-future: #2196f3; + --color-button-bg: #00e676; + --color-button-text: #1b5e20; + --color-rank-bg: #e8eaf6; + --color-rank-text: #3f51b5; +} + +body { + margin: 0; + font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + background-color: var(--color-neutral-bg); +} + +.app-container { + min-height: 100vh; + padding-bottom: 40px; +} + +.header-wrapper { + background-color: var(--color-header-bg); + color: white; + padding: 20px 0; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); +} + +.header-content { + max-width: 800px; + margin: 0 auto; + padding: 0 20px; +} + +.header-title { + margin: 0 0 15px 0; + font-size: 1.8rem; +} + +.search-form { + display: flex; + gap: 10px; +} + +.search-input { + padding: 12px; + font-size: 16px; + flex-grow: 1; + border: none; + border-radius: 6px; + outline: none; +} + +.search-button { + padding: 12px 25px; + font-size: 16px; + background-color: var(--color-button-bg); + color: var(--color-button-text); + border: none; + border-radius: 6px; + cursor: pointer; + font-weight: bold; +} + +.search-button:disabled { + opacity: 0.7; + cursor: not-allowed; +} + +.error-message { + margin-top: 15px; + padding: 10px; + background-color: var(--color-red-bg); + color: var(--color-red-text); + border-radius: 4px; + font-size: 0.9rem; +} + +.main-content { + max-width: 800px; + margin: 20px auto; + padding: 0 20px; +} + +.event-info-bar { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + color: var(--color-text-sub); + font-size: 0.9rem; +} +.status-card { + background-color: var(--color-card-bg); + padding: 20px; + border-radius: 12px; + margin-bottom: 30px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + border-left-width: 5px; + border-left-style: solid; +} +.status-title { + margin: 0 0 5px 0; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; +} + +.status-content { + display: flex; + align-items: center; + justify-content: space-between; +} + +.status-match-name { + font-size: 2rem; + font-weight: 800; + color: var(--color-text-main); +} + +.status-badge { + padding: 5px 12px; + border-radius: 20px; + font-size: 0.85rem; + font-weight: bold; +} + +.status-empty { + color: #999; + font-style: italic; +} + +.section-title { + font-size: 1.4rem; + color: var(--color-text-main); + border-bottom: 2px solid #ddd; + padding-bottom: 10px; + margin-bottom: 20px; +} + +.rank-card { + background-color: var(--color-card-bg); + border-radius: 12px; + padding: 30px; + text-align: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.rank-label { + font-size: 1rem; + color: var(--color-text-sub); + text-transform: uppercase; + letter-spacing: 1px; + margin-bottom: 10px; +} + +.rank-number { + font-size: 4rem; + font-weight: bold; + color: var(--color-rank-text); + line-height: 1; +} + +.rank-record { + margin-top: 20px; + display: inline-block; + background-color: var(--color-rank-bg); + padding: 8px 20px; + border-radius: 20px; + color: var(--color-rank-text); + font-weight: bold; +} + +.empty-state { + text-align: center; + padding: 40px; + color: #888; + background-color: var(--color-card-bg); + border-radius: 12px; +} + +.match-card { + background-color: var(--color-card-bg); + border-radius: 12px; + margin-bottom: 20px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + overflow: hidden; +} + +.match-header { + padding: 15px 20px; + border-bottom: 1px solid #eee; + display: flex; + justify-content: space-between; + align-items: center; + background-color: #fafafa; +} + +.match-title { + font-size: 1.2rem; + font-weight: bold; + color: var(--color-text-main); +} + +.match-meta { + text-align: right; + display: flex; + flex-direction: column; + align-items: flex-end; +} + +.match-time { + font-size: 0.9rem; + color: var(--color-text-sub); + display: flex; + align-items: center; + gap: 10px; +} + +.match-countdown { + font-weight: bold; + font-size: 0.85rem; + margin-top: 4px; +} + +.alliance-row { + display: flex; +} + +.alliance-block { + flex: 1; + padding: 15px; +} + +.alliance-header { + font-weight: bold; + margin-bottom: 10px; + font-size: 0.9rem; + text-transform: uppercase; +} + +.team-row { + display: flex; + align-items: center; + margin-bottom: 6px; +} + +.team-number { + width: 50px; + font-weight: bold; + color: var(--color-text-main); +} + +.team-name { + font-size: 0.9rem; + color: var(--color-text-sub); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.you-badge { + margin-left: auto; + font-size: 0.7rem; + color: white; + padding: 2px 6px; + border-radius: 4px; +} diff --git a/apps/playoff-schedule/frontend/src/Hooks/LocalStorageHook.tsx b/apps/playoff-schedule/frontend/src/Hooks/LocalStorageHook.tsx new file mode 100644 index 0000000..2461286 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/Hooks/LocalStorageHook.tsx @@ -0,0 +1,37 @@ +// בס"ד +import { useState } from "react"; + +const useLocalStorage = ( + key: string, + initialValue: T +): [T, (val: T | ((val: T) => T)) => void] => { + const [storedValue, setStoredValue] = useState(() => { + try { + if (typeof window === "undefined") { + return initialValue; + } + const item = window.localStorage.getItem(key); + return item ? JSON.parse(item) : initialValue; + } catch (error) { + console.error(error); + return initialValue; + } + }); + + const setValue = (value: T | ((val: T) => T)) => { + try { + const valueToStore = + value instanceof Function ? value(storedValue) : value; + setStoredValue(valueToStore); + if (typeof window !== "undefined") { + window.localStorage.setItem(key, JSON.stringify(valueToStore)); + } + } catch (error) { + console.error(error); + } + }; + + return [storedValue, setValue]; +}; + +export default useLocalStorage; diff --git a/apps/playoff-schedule/frontend/src/Hooks/useEventData.ts b/apps/playoff-schedule/frontend/src/Hooks/useEventData.ts new file mode 100644 index 0000000..b8e64b7 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/Hooks/useEventData.ts @@ -0,0 +1,131 @@ +// בס"ד +import { useState, useCallback, useEffect } from "react"; +import { urlMatches, type MatchesSimpleType } from "../endpoints/MatchSimple"; +import { + urlTeamsInEvent, + type TeamsInEventType, +} from "../endpoints/TeamsSimple"; +import { urlRankings } from "../utils/rankingsUtils"; +import { fetchFromProxy } from "../utils/apiUtils"; +import { sortMatches } from "../utils/matchUtils"; +import type { RankItem, RankingsResponse } from "../types"; +import { targetTeamKey, refreshIntervalMs } from "../config/frcConfig"; + +export type SearchStatus = "idle" | "searching" | "success" | "error"; + +interface UseEventDataReturn { + teams: TeamsInEventType[]; + allMatches: MatchesSimpleType[]; + teamRank: RankItem | null; + searchStatus: SearchStatus; + performSearch: (eventKey: string) => Promise; + resetSearch: () => void; +} + +export const useEventData = ( + activeEventKey: string, + setActiveEventKey: (key: string) => void +): UseEventDataReturn => { + const [teams, setTeams] = useState([]); + const [allMatches, setAllMatches] = useState([]); + const [teamRank, setTeamRank] = useState(null); + const [searchStatus, setSearchStatus] = useState("idle"); + + const resetSearch = useCallback(() => { + setSearchStatus("searching"); + setAllMatches([]); + setTeams([]); + setTeamRank(null); + }, []); + + const fetchEventData = useCallback(async (eventKey: string) => { + const teamsUrl = urlTeamsInEvent(eventKey); + const matchesUrl = urlMatches(eventKey); + const rankingsUrl = urlRankings(eventKey); + + return Promise.all([ + fetchFromProxy(teamsUrl), + fetchFromProxy(matchesUrl), + fetchFromProxy(rankingsUrl).catch(() => ({ + rankings: [], + })), + ]); + }, []); + + const performSearch = useCallback( + async (eventKey: string) => { + if (!eventKey) return; + + resetSearch(); + setActiveEventKey(eventKey); + + try { + const [teamsData, matchesData, rankingsData] = + await fetchEventData(eventKey); + + if (Array.isArray(teamsData) && Array.isArray(matchesData)) { + setTeams(teamsData); + matchesData.sort(sortMatches); + setAllMatches(matchesData); + setTeamRank( + rankingsData.rankings.find((r) => r.team_key === targetTeamKey) ?? + null + ); + setSearchStatus("success"); + } else { + setSearchStatus("error"); + } + } catch { + setSearchStatus("error"); + } + }, + [setActiveEventKey, resetSearch, fetchEventData] + ); + + useEffect(() => { + if (activeEventKey && searchStatus === "idle") { + void performSearch(activeEventKey); + } + }, [activeEventKey, performSearch, searchStatus]); + + useEffect(() => { + if (!(searchStatus === "success" && activeEventKey)) { + return undefined; + } + + const intervalId = setInterval(() => { + const matchesUrl = urlMatches(activeEventKey); + const rankingsUrl = urlRankings(activeEventKey); + + void fetchFromProxy(matchesUrl) + .then((data) => { + if (Array.isArray(data)) { + data.sort(sortMatches); + setAllMatches(data); + } + }) + .catch(console.error); + + void fetchFromProxy(rankingsUrl) + .then((data) => { + const myRank = + data.rankings.find((r) => r.team_key === targetTeamKey) ?? null; + setTeamRank(myRank); + }) + .catch(console.error); + }, refreshIntervalMs); + + return () => { + clearInterval(intervalId); + }; + }, [activeEventKey, searchStatus]); + + return { + teams, + allMatches, + teamRank, + searchStatus, + performSearch, + resetSearch, + }; +}; diff --git a/apps/playoff-schedule/frontend/src/Hooks/useMatchProcessing.ts b/apps/playoff-schedule/frontend/src/Hooks/useMatchProcessing.ts new file mode 100644 index 0000000..2c20bee --- /dev/null +++ b/apps/playoff-schedule/frontend/src/Hooks/useMatchProcessing.ts @@ -0,0 +1,104 @@ +// בס"ד +import { useMemo } from "react"; +import type { MatchesSimpleType } from "../endpoints/MatchSimple"; +import { sortMatches, getMatchTime } from "../utils/matchUtils"; +import { + targetTeamKey, + timeMultiplier, + matchTimeMissing, + dayInSeconds, + firstIndex, + nextMatchLimit, + noGap, +} from "../config/frcConfig"; + +interface UseMatchProcessingReturn { + currentGlobalMatch: MatchesSimpleType | undefined; + targetTeamMatches: MatchesSimpleType[]; + futureMatches: MatchesSimpleType[]; + isEventOver: boolean; + isTeamDone: boolean; + isFutureEvent: boolean; +} + +export const useMatchProcessing = ( + allMatches: MatchesSimpleType[] +): UseMatchProcessingReturn => { + return useMemo(() => { + // i will leave this here so you can check the code with different dates. + + // normal one + const currentTimeSecs = Math.floor(Date.now() / timeMultiplier); + + // testing 2025isios + // const currentTimeSecs = Math.floor( + // new Date("2025-10-08T13:44:00").getTime() / timeMultiplier + // ); + + //testing 2025iscmp + // const currentTimeSecs = Math.floor( + // new Date("2025-03-27T10:00:00").getTime() / timeMultiplier + // ); + + // testing 2024iscmp + // const currentTimeSecs = Math.floor( + // new Date("2024-03-21T15:00:00").getTime() / timeMultiplier + // ); + + // testing 2025cmptx + //const currentTimeSecs = Math.floor(new Date("2025-04-19T10:00:00").getTime() / timeMultiplier); + + const futureMatchesArr = allMatches.filter((match) => { + const time = getMatchTime(match); + return time === matchTimeMissing || time > currentTimeSecs; + }); + + const pastMatchesArr = allMatches.filter((match) => { + const time = getMatchTime(match); + return time > matchTimeMissing && time <= currentTimeSecs; + }); + + futureMatchesArr.sort(sortMatches); + + const currentMatch = + futureMatchesArr.length > noGap + ? futureMatchesArr[firstIndex] + : undefined; + + const teamFutureMatches = futureMatchesArr.filter( + (match) => + match.alliances.blue.team_keys.includes(targetTeamKey) || + match.alliances.red.team_keys.includes(targetTeamKey) + ); + + const teamPastMatches = pastMatchesArr.filter( + (match) => + match.alliances.blue.team_keys.includes(targetTeamKey) || + match.alliances.red.team_keys.includes(targetTeamKey) + ); + + const hasEventEnded = + futureMatchesArr.length === noGap && allMatches.length > noGap; + + const hasTeamDone = + !hasEventEnded && + teamFutureMatches.length === noGap && + teamPastMatches.length > noGap; + + const isNextMatchInFarFuture = currentMatch + ? getMatchTime(currentMatch) > currentTimeSecs + dayInSeconds && + getMatchTime(currentMatch) !== matchTimeMissing + : false; + + return { + currentGlobalMatch: currentMatch, + targetTeamMatches: hasTeamDone + ? [] + : teamFutureMatches.slice(firstIndex, nextMatchLimit), + futureMatches: futureMatchesArr, + isEventOver: hasEventEnded, + isTeamDone: hasTeamDone, + isFutureEvent: isNextMatchInFarFuture, + }; + }, [allMatches]); +}; diff --git a/apps/playoff-schedule/frontend/src/assets/greenblitz.svg b/apps/playoff-schedule/frontend/src/assets/greenblitz.svg new file mode 100644 index 0000000..e8eb8c5 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/assets/greenblitz.svg @@ -0,0 +1,38 @@ + + + + + + + + + + diff --git a/apps/playoff-schedule/frontend/src/components/Alliance.tsx b/apps/playoff-schedule/frontend/src/components/Alliance.tsx new file mode 100644 index 0000000..bfbf59f --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/Alliance.tsx @@ -0,0 +1,75 @@ +// בס"ד +import type React from "react"; +import { targetTeamKey, sliceStart } from "../config/frcConfig"; + +interface AllianceProps { + teamKeys: string[]; + teamNameMap: Record; + allianceColor: "red" | "blue"; + isTargetTeamInAlliance: boolean; +} + +export const Alliance: React.FC = ({ + teamKeys, + teamNameMap, + allianceColor, + isTargetTeamInAlliance, +}) => { + const colorClasses = { + red: { + border: "border-red-400 dark:border-red-500", + bg: "bg-gray-100 dark:bg-gray-700/50", + text: "text-red-700 dark:text-red-400", + badge: "bg-red-700 dark:bg-red-600", + }, + blue: { + border: "border-blue-400 dark:border-blue-500", + bg: "bg-gray-100 dark:bg-gray-700/50", + text: "text-blue-700 dark:text-blue-400", + badge: "bg-blue-700 dark:bg-blue-600", + }, + }; + + const colors = colorClasses[allianceColor]; + + return ( +
+
+ {allianceColor === "red" ? "Red" : "Blue"} Alliance +
+ {teamKeys.map((teamKey) => { + const teamNumber = teamKey.slice(sliceStart); + const teamName = teamNameMap[teamKey] ?? "Unknown"; + const isTargetTeam = teamKey === targetTeamKey; + return ( +
+ + {teamNumber} + + + {teamName} + + {isTargetTeam && ( + + YOU + + )} +
+ ); + })} +
+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/components/CurrentMatchStatus.tsx b/apps/playoff-schedule/frontend/src/components/CurrentMatchStatus.tsx new file mode 100644 index 0000000..6edd4f5 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/CurrentMatchStatus.tsx @@ -0,0 +1,57 @@ +// בס"ד +import type React from "react"; +import type { MatchesSimpleType } from "../endpoints/MatchSimple"; +import { getMatchDisplayName } from "../utils/matchDisplayUtils"; +import { noGap } from "../config/frcConfig"; + +interface CurrentMatchStatusProps { + currentMatch: MatchesSimpleType | undefined; + isFutureEvent: boolean; + allMatchesCount: number; +} + +export const CurrentMatchStatus: React.FC = ({ + currentMatch, + isFutureEvent, + allMatchesCount, +}) => { + return ( +
+

+ {isFutureEvent ? "Upcoming Event" : "Current Field Status"} +

+ {currentMatch !== undefined ? ( +
+ + {getMatchDisplayName(currentMatch)} + + + {isFutureEvent ? "SCHEDULED" : "IN PROGRESS"} + +
+ ) : ( +

+ {allMatchesCount > noGap ? "Event Concluded" : "No matches scheduled"} +

+ )} +
+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/components/EmptyState.tsx b/apps/playoff-schedule/frontend/src/components/EmptyState.tsx new file mode 100644 index 0000000..4073176 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/EmptyState.tsx @@ -0,0 +1,22 @@ +// בס"ד +import type React from "react"; +import { targetTeamNumber } from "../config/frcConfig"; + +interface EmptyStateProps { + isTeamDone: boolean; +} + +export const EmptyState: React.FC = ({ isTeamDone }) => { + return ( +
+ {isTeamDone ? ( +

+ Team {targetTeamNumber} has completed all scheduled matches for this + event (or for today). +

+ ) : ( +

No upcoming matches found for Team {targetTeamNumber}.

+ )} +
+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/components/EventInfoBar.tsx b/apps/playoff-schedule/frontend/src/components/EventInfoBar.tsx new file mode 100644 index 0000000..c7e066c --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/EventInfoBar.tsx @@ -0,0 +1,23 @@ +// בס"ד +import type React from "react"; + +interface EventInfoBarProps { + eventKey: string; + teamCount: number; +} + +export const EventInfoBar: React.FC = ({ + eventKey, + teamCount, +}) => { + return ( +
+ + Event: {eventKey} + + + Teams: {teamCount} + +
+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/components/FinalResults.tsx b/apps/playoff-schedule/frontend/src/components/FinalResults.tsx new file mode 100644 index 0000000..bedeb9d --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/FinalResults.tsx @@ -0,0 +1,32 @@ +// בס"ד +import type React from "react"; +import type { RankItem } from "../types"; + +interface FinalResultsProps { + teamRank: RankItem|null; +} + +export const FinalResults: React.FC = ({ teamRank }) => { + return ( +
+ {teamRank ? ( + <> +
+ Final Rank +
+
+ #{teamRank.rank} +
+
+ Record: {teamRank.record.wins}-{teamRank.record.losses}- + {teamRank.record.ties} +
+ + ) : ( +

+ Rank data not available for this event. +

+ )} +
+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/components/Header.tsx b/apps/playoff-schedule/frontend/src/components/Header.tsx new file mode 100644 index 0000000..f2dafa0 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/Header.tsx @@ -0,0 +1,48 @@ +// בס"ד +import type React from "react"; + +interface HeaderProps { + inputEventKey: string; + onInputChange: (value: string) => void; + onSearchSubmit: (event: React.FormEvent) => void; + searchStatus: "idle" | "searching" | "success" | "error"; +} + +export const Header: React.FC = ({ + inputEventKey, + onInputChange, + onSearchSubmit, + searchStatus, +}) => { + return ( +
+
+

+ GB Playoff schedule +

+
+ { onInputChange(event.target.value); }} + className="search-input flex-1 rounded-md border-2 border-slate-400 dark:border-slate-500 bg-slate-600 dark:bg-slate-700 p-3 text-base text-white outline-none transition-colors placeholder:text-slate-300 dark:placeholder:text-slate-400 focus:border-blue-400 dark:focus:border-blue-500" + /> + +
+ + {searchStatus === "error" && ( +
+ Event not found. +
+ )} +
+
+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/components/MatchCard.tsx b/apps/playoff-schedule/frontend/src/components/MatchCard.tsx new file mode 100644 index 0000000..7b747a8 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/MatchCard.tsx @@ -0,0 +1,72 @@ +// בס"ד +import type React from "react"; +import type { MatchesSimpleType } from "../endpoints/MatchSimple"; +import { getMatchDisplayName } from "../utils/matchDisplayUtils"; +import { formatMatchTime } from "../utils/matchDisplayUtils"; +import { Alliance } from "./Alliance"; +import { + targetTeamKey, + timeMultiplier, + nextMatchLimit, + noGap, + notFoundIndex, +} from "../config/frcConfig"; + +interface MatchCardProps { + match: MatchesSimpleType; + teamNameMap: Record; + futureMatches: MatchesSimpleType[]; +} + +export const MatchCard: React.FC = ({ + match, + teamNameMap, + futureMatches, +}) => { + const effectiveTime = match.predicted_time ?? match.time ?? undefined; + const predictedDate = formatMatchTime(effectiveTime, timeMultiplier); + + const matchIndex = futureMatches.findIndex((m) => m.key === match.key); + const matchesAway = matchIndex > notFoundIndex ? matchIndex : noGap; + + const isRedAlliance = match.alliances.red.team_keys.includes(targetTeamKey); + + return ( +
+
+
+ + {getMatchDisplayName(match)} + +
+
+
+ {predictedDate} +
+
+ {matchesAway <= noGap ? "PLAYING NOW" : `IN ${matchesAway} MATCHES`} +
+
+
+ +
+ + +
+
+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/components/SectionTitle.tsx b/apps/playoff-schedule/frontend/src/components/SectionTitle.tsx new file mode 100644 index 0000000..9e40028 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/components/SectionTitle.tsx @@ -0,0 +1,17 @@ +// בס"ד +import type React from "react"; +import { targetTeamNumber } from "../config/frcConfig"; + +interface SectionTitleProps { + isEventOver: boolean; +} + +export const SectionTitle: React.FC = ({ isEventOver }) => { + return ( +

+ {isEventOver + ? `Final Results: Team ${targetTeamNumber}` + : `Upcoming: Team ${targetTeamNumber}`} +

+ ); +}; diff --git a/apps/playoff-schedule/frontend/src/config/frcConfig.ts b/apps/playoff-schedule/frontend/src/config/frcConfig.ts new file mode 100644 index 0000000..e005560 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/config/frcConfig.ts @@ -0,0 +1,37 @@ +// בס"ד + +export const targetTeamNumber = 4590; +export const backendPort = 4590; + +export const refreshIntervalMs = 30000; +export const timeMultiplier = 1000; + +export const sliceStart = 3; +export const firstIndex = 0; +export const nextMatchLimit = 2; +export const noGap = 0; + +export const matchTimeDefault = 0; +export const matchTimeMissing = 0; +export const dayInSeconds = 86400; + +export const sortABeforeB = -1; +export const sortBBeforeA = 1; + +export const weightQm = 1; +export const weightEf = 2; +export const weightQf = 3; +export const weightSf = 4; +export const weightF = 5; +export const weightDefault = 99; +export const defaultLevelWeight = 1; +export const levelWeights = { + 1: weightQm, + 2: weightEf, + 3: weightQf, + 4: weightSf, + 5: weightF, +}; +export const targetTeamKey = `frc${targetTeamNumber}`; +export const backendBaseUrl = `http://localhost:${backendPort}/api/v1/tba`; +export const notFoundIndex = -1; diff --git a/apps/playoff-schedule/frontend/src/endpoints/EventsSimple.tsx b/apps/playoff-schedule/frontend/src/endpoints/EventsSimple.tsx new file mode 100644 index 0000000..f66d301 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/endpoints/EventsSimple.tsx @@ -0,0 +1,27 @@ +// בס"ד +import * as t from "io-ts"; +import { stringOrNull } from "../utils/TypeUtils"; + +export const simpleEventsInYear = t.type({ + //did + city: stringOrNull, + country: stringOrNull, + district: t.unknown /*null*/, + end_date: t.string, + event_code: t.string, + event_type: t.number, + key: t.string, + name: t.string, + start_date: t.string, + state_prov: stringOrNull, + year: t.number, +}); +export type EventsInYearType = typeof simpleEventsInYear._A; + +/** + * + * @param year in urlEventsInYear switch to curr year: now.getFullYear() + * @returns + */ +export const urlEventsInYear = (year: number /*or curr time*/) => + `https://www.thebluealliance.com/api/v3/events/${year}/simple`; diff --git a/apps/playoff-schedule/frontend/src/endpoints/MatchSimple.tsx b/apps/playoff-schedule/frontend/src/endpoints/MatchSimple.tsx new file mode 100644 index 0000000..276b0a7 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/endpoints/MatchSimple.tsx @@ -0,0 +1,27 @@ +// בס"ד + +import * as t from "io-ts"; +import { simpleAlliance } from "./SimpleAlliance"; +import { numberOrNull } from "../utils/TypeUtils"; + +export const matchSimple = t.type({ + actual_time: numberOrNull, + alliances: t.type({ + blue: simpleAlliance, + red: simpleAlliance, + }), + comp_level: t.string, + event_key: t.string, + key: t.string, + match_number: t.number, + predicted_time: numberOrNull, + set_number: t.number, + time: numberOrNull, + winning_alliance: t.string, +}); + +export type MatchesSimpleType = typeof matchSimple._A; + +export const urlMatches = (eventKey: string) => + `/events/${eventKey}/matches`; + diff --git a/apps/playoff-schedule/frontend/src/endpoints/RankingSimple.tsx b/apps/playoff-schedule/frontend/src/endpoints/RankingSimple.tsx new file mode 100644 index 0000000..2205258 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/endpoints/RankingSimple.tsx @@ -0,0 +1,4 @@ +// בס"ד + +export const urlRankings = (eventKey: string) => +`https://www.thebluealliance.com/api/v3/event/${eventKey}/rankings`; \ No newline at end of file diff --git a/apps/playoff-schedule/frontend/src/endpoints/SimpleAlliance.tsx b/apps/playoff-schedule/frontend/src/endpoints/SimpleAlliance.tsx new file mode 100644 index 0000000..8953a64 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/endpoints/SimpleAlliance.tsx @@ -0,0 +1,8 @@ +// בס"ד +import * as t from "io-ts"; +export const simpleAlliance = t.type({ + dq_team_keys: t.array(t.string), + score: t.number, + surrogate_team_keys: t.array(t.string), + team_keys: t.array(t.string), +}); diff --git a/apps/playoff-schedule/frontend/src/endpoints/TeamsSimple.tsx b/apps/playoff-schedule/frontend/src/endpoints/TeamsSimple.tsx new file mode 100644 index 0000000..f89d2c8 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/endpoints/TeamsSimple.tsx @@ -0,0 +1,17 @@ +// בס"ד +import * as t from "io-ts"; +import { stringOrNull } from "../utils/TypeUtils"; + +export const simpleTeamsInEvent = t.type({//did + city: stringOrNull, + country: stringOrNull, + key: t.string, + name: t.string, + nickname: t.string, + state_prov: stringOrNull, + team_number: t.number, +}); +export type TeamsInEventType = typeof simpleTeamsInEvent._A; + +export const urlTeamsInEvent = (eventKey: string) => + `/events/${eventKey}/teams`; \ No newline at end of file diff --git a/apps/playoff-schedule/frontend/src/index.css b/apps/playoff-schedule/frontend/src/index.css new file mode 100644 index 0000000..1817850 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/index.css @@ -0,0 +1,100 @@ +@import "tailwindcss"; +:root { + font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + width: 100%; + margin: 0; + padding: 0; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/apps/playoff-schedule/frontend/src/main.tsx b/apps/playoff-schedule/frontend/src/main.tsx new file mode 100644 index 0000000..e37945f --- /dev/null +++ b/apps/playoff-schedule/frontend/src/main.tsx @@ -0,0 +1,11 @@ +// בס"ד +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App"; + +createRoot(document.getElementById("root")!).render( + + + +); diff --git a/apps/playoff-schedule/frontend/src/styles/classes.ts b/apps/playoff-schedule/frontend/src/styles/classes.ts new file mode 100644 index 0000000..bfe614d --- /dev/null +++ b/apps/playoff-schedule/frontend/src/styles/classes.ts @@ -0,0 +1,43 @@ +// בס"ד +// Common CSS class combinations for consistency + +export const classes = { + // Layout + container: "mx-auto max-w-4xl px-5", + mainContent: "mx-auto mt-6 max-w-4xl px-5", + + // Cards + card: "rounded-xl bg-white shadow-sm", + cardHover: "transition-shadow hover:shadow-md", + cardPadding: "p-5", + + // Status badges + badge: "rounded-full px-3 py-1 text-xs font-bold", + badgeBlue: "bg-blue-50 text-blue-500", + badgeOrange: "bg-orange-50 text-orange-700", + badgeRed: "bg-red-50 text-red-800", + + // Text + title: "text-3xl font-normal", + sectionTitle: "mb-5 border-b-2 border-gray-200 pb-2 text-2xl text-gray-800", + subtitle: "text-sm font-bold uppercase tracking-wider", + + // Colors + textGray: "text-gray-900", + textGrayLight: "text-gray-500", + textGrayLighter: "text-gray-400", + + // Borders + borderLeft: "border-l-[6px]", + borderBlue: "border-blue-500", + borderAmber: "border-amber-500", + + // Search input + searchInput: + "flex-1 rounded-md border-2 border-slate-400 bg-slate-600 p-3 text-base text-white outline-none transition-colors placeholder:text-slate-300 focus:border-blue-400", + + // Buttons + button: + "rounded-md px-6 py-3 text-base font-bold transition disabled:opacity-70", + buttonPrimary: "bg-slate-500 text-white hover:bg-slate-400", +} as const; diff --git a/apps/playoff-schedule/frontend/src/types.ts b/apps/playoff-schedule/frontend/src/types.ts new file mode 100644 index 0000000..aa9fcb1 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/types.ts @@ -0,0 +1,46 @@ +// בס"ד + +export interface Alliance { + score: number; + team_keys: string[]; + surrogate_team_keys?: string[]; + dq_team_keys?: string[]; +} + +export interface Alliances { + blue: Alliance; + red: Alliance; +} + +export interface MatchesSimpleType { + key: string; + comp_level: string; + set_number: number; + match_number: number; + alliances: Alliances; + winning_alliance: string; + event_key: string; + time?: number; + predicted_time?: number; + actual_time?: number; +} + +export interface TeamsInEventType { + key: string; + team_number: number; + nickname: string; + name: string; + city: string; + state_prov: string; + country: string; +} + +export interface RankItem { + rank: number; + team_key: string; + record: { wins: number; losses: number; ties: number }; +} + +export interface RankingsResponse { + rankings: RankItem[]; +} diff --git a/apps/playoff-schedule/frontend/src/utils/TypeUtils.tsx b/apps/playoff-schedule/frontend/src/utils/TypeUtils.tsx new file mode 100644 index 0000000..735fc9e --- /dev/null +++ b/apps/playoff-schedule/frontend/src/utils/TypeUtils.tsx @@ -0,0 +1,4 @@ +// בס"ד +import * as t from "io-ts"; +export const numberOrNull = t.union([t.number, t.null]); //for if type is null +export const stringOrNull = t.union([t.string, t.null]); //for if type is null diff --git a/apps/playoff-schedule/frontend/src/utils/apiUtils.ts b/apps/playoff-schedule/frontend/src/utils/apiUtils.ts new file mode 100644 index 0000000..ceebae7 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/utils/apiUtils.ts @@ -0,0 +1,15 @@ +// בס"ד +import { backendBaseUrl } from "../config/frcConfig"; + +const joinUrl = (path: string): string => + `${backendBaseUrl}${path.startsWith("/") ? path : `/${path}`}`; + +export const fetchFromProxy = async (targetPath: string): Promise => { + const fullUrl = joinUrl(targetPath); + return fetch(fullUrl).then((response) => { + if (response.ok) { + return response.json() as Promise; + } + throw new Error(`HTTP error status: ${response.status}`); + }); +}; diff --git a/apps/playoff-schedule/frontend/src/utils/matchDisplayUtils.ts b/apps/playoff-schedule/frontend/src/utils/matchDisplayUtils.ts new file mode 100644 index 0000000..7d53d56 --- /dev/null +++ b/apps/playoff-schedule/frontend/src/utils/matchDisplayUtils.ts @@ -0,0 +1,31 @@ +// בס"ד +import type { MatchesSimpleType } from "../endpoints/MatchSimple"; + +export const getMatchDisplayName = (match: MatchesSimpleType): string => { + const level = match.comp_level.toUpperCase(); + switch (level) { + case "QM": + return `Quals ${match.match_number}`; + case "QF": + return `Quarterfinal ${match.set_number}, Match ${match.match_number}`; + case "SF": + return `Semifinal ${match.set_number}, Match ${match.match_number}`; + case "F": + return `Finals Match ${match.match_number}`; + case "EF": + return `First Round ${match.set_number}, Match ${match.match_number}`; + default: + return `${level} ${match.match_number}`; + } +}; + +export const formatMatchTime = ( + time: number | undefined, + timeMultiplier: number +): string => { + if (!time) return "TBD"; + return new Date(time * timeMultiplier).toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + }); +}; diff --git a/apps/playoff-schedule/frontend/src/utils/matchUtils.ts b/apps/playoff-schedule/frontend/src/utils/matchUtils.ts new file mode 100644 index 0000000..894c8ba --- /dev/null +++ b/apps/playoff-schedule/frontend/src/utils/matchUtils.ts @@ -0,0 +1,50 @@ +// בס"ד +import type { MatchesSimpleType } from "../endpoints/MatchSimple"; +import { + matchTimeDefault, + matchTimeMissing, + sortABeforeB, + sortBBeforeA, + weightQm, + weightEf, + weightQf, + weightSf, + weightF, + weightDefault, +} from "../config/frcConfig"; + +export const getMatchTime = (match: MatchesSimpleType): number => + match.predicted_time ?? match.time ?? matchTimeDefault; + +const getLevelWeight = (level: string): number => + level === 'qm' ? weightQm + : level === 'ef' ? weightEf + : level === 'qf' ? weightQf + : level === 'sf' ? weightSf + : level === 'f' ? weightF + : weightDefault; + +export const sortMatches = (a: MatchesSimpleType, b: MatchesSimpleType) => { + const timeA = getMatchTime(a); + const timeB = getMatchTime(b); + const weightA = getLevelWeight(a.comp_level); + const weightB = getLevelWeight(b.comp_level); + + if (timeA > matchTimeMissing && timeB > matchTimeMissing) { + return timeA - timeB; + } + + if (timeA === matchTimeMissing && timeB > matchTimeMissing) { + return sortABeforeB; + } + + if (timeA > matchTimeMissing && timeB === matchTimeMissing) { + return sortBBeforeA; + } + + if (weightA !== weightB) { + return weightA - weightB; + } + + return a.match_number - b.match_number; +}; diff --git a/apps/playoff-schedule/frontend/src/utils/rankingsUtils.ts b/apps/playoff-schedule/frontend/src/utils/rankingsUtils.ts new file mode 100644 index 0000000..7f6082f --- /dev/null +++ b/apps/playoff-schedule/frontend/src/utils/rankingsUtils.ts @@ -0,0 +1,3 @@ +// בס"ד +export const urlRankings = (eventKey: string) => + `/events/${eventKey}/rankings`; diff --git a/apps/playoff-schedule/frontend/start.ts b/apps/playoff-schedule/frontend/start.ts new file mode 100644 index 0000000..a99498b --- /dev/null +++ b/apps/playoff-schedule/frontend/start.ts @@ -0,0 +1,24 @@ +// בס"ד +import express from "express"; +import path from "path"; + +const app = express(); + +const defaultPort = 80; +const securePort = 443; +const port = parseInt(process.env.FRONTEND_PORT ?? defaultPort.toString()); +const protocol = port === securePort ? "https" : "http"; + +const dirname = path.dirname(__filename); +const distDirectory = path.join(dirname, "dist"); +const indexHTML = path.join(distDirectory, "index.html"); + +app.use(express.static(distDirectory)); + +app.get(/^(.*)$/, (req, res) => { + res.sendFile(indexHTML); +}); + +app.listen(port, () => { + console.log(`Production server running at ${protocol}://localhost:${port}`); +}); diff --git a/apps/playoff-schedule/frontend/tsconfig.app.json b/apps/playoff-schedule/frontend/tsconfig.app.json new file mode 100644 index 0000000..a9b5a59 --- /dev/null +++ b/apps/playoff-schedule/frontend/tsconfig.app.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/apps/playoff-schedule/frontend/tsconfig.json b/apps/playoff-schedule/frontend/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/apps/playoff-schedule/frontend/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/apps/playoff-schedule/frontend/tsconfig.node.json b/apps/playoff-schedule/frontend/tsconfig.node.json new file mode 100644 index 0000000..8a67f62 --- /dev/null +++ b/apps/playoff-schedule/frontend/tsconfig.node.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/apps/playoff-schedule/frontend/turbo.json b/apps/playoff-schedule/frontend/turbo.json new file mode 100644 index 0000000..52e8c76 --- /dev/null +++ b/apps/playoff-schedule/frontend/turbo.json @@ -0,0 +1,12 @@ +{ + "extends": [ + "//" + ], + "tasks": { + "build": { + "outputs": [ + "dist/**" + ] + } + } +} diff --git a/apps/playoff-schedule/frontend/vite.config.ts b/apps/playoff-schedule/frontend/vite.config.ts new file mode 100644 index 0000000..37eb678 --- /dev/null +++ b/apps/playoff-schedule/frontend/vite.config.ts @@ -0,0 +1,18 @@ +// בס"ד +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; + + +// https://vite.dev/config/ +export default defineConfig({ + server: { port: 80 }, + plugins: [ + react({ + babel: { + plugins: [["babel-plugin-react-compiler"]], + }, + }), + tailwindcss(), + ], +}); diff --git a/apps/template/docker-compose.yml b/apps/template/docker-compose.yml deleted file mode 100644 index 96e13a2..0000000 --- a/apps/template/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -services: - frontend: - build: - context: ./frontend # Looks for Dockerfile in the ./frontend directory - ports: - - "${FRONTEND_PORT}:80" # Maps host:${FRONTEND_PORT} to container:80 - - backend: - build: - context: ./backend # Looks for Dockerfile in the ./backend directory - ports: - - "${BACKEND_PORT}:4590" # Maps host:${BACKEND_PORT} to container:4590 diff --git a/package-lock.json b/package-lock.json index 43dd24c..46bc34a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,12 +12,15 @@ ], "dependencies": { "@tailwindcss/vite": "^4.1.17", + "cors": "^2.8.5", "dotenv": "^17.2.3", "dotenv-cli": "^11.0.0", "eslint-plugin-bsd": "^1.0.0", "eslint-plugin-react": "^7.37.5", "express": "^5.1.0", "http-status-codes": "^2.3.0", + "io-ts": "^2.2.22", + "react": "^19.2.1", "tailwindcss": "^4.1.17", "tsx": "^4.21.0" }, @@ -39,9 +42,9 @@ "node": ">=18" } }, - "apps/backend": { + "apps/playoff-schedule/backend": { + "name": "playoff-schedule-backend", "version": "1.0.0", - "extraneous": true, "license": "ISC", "dependencies": { "process": "^0.11.10" @@ -50,28 +53,9 @@ "@types/node": "^24.8.1" } }, - "apps/docs": { - "version": "0.1.0", - "extraneous": true, - "dependencies": { - "@repo/ui": "*", - "next": "^16.0.1", - "react": "^19.2.0", - "react-dom": "^19.2.0" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/node": "^22.15.3", - "@types/react": "19.2.2", - "@types/react-dom": "19.2.2", - "eslint": "^9.39.1", - "typescript": "5.9.2" - } - }, - "apps/frontend": { + "apps/playoff-schedule/frontend": { + "name": "playoff-schedule-frontend", "version": "1.0.0", - "extraneous": true, "license": "ISC", "dependencies": { "@tailwindcss/vite": "^4.1.16", @@ -86,15 +70,21 @@ "@types/react-dom": "^19.1.9", "@vitejs/plugin-react": "^5.0.4", "babel-plugin-react-compiler": "^19.1.0-rc.3", - "eslint": "^9.36.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.22", "globals": "^16.4.0", - "typescript": "~5.9.3", - "typescript-eslint": "^8.45.0", "vite": "^7.1.7" } }, + "apps/playoff-schedule/frontend/node_modules/globals": { + "version": "16.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "apps/template/backend": { "name": "template-backend", "version": "1.0.0", @@ -129,8 +119,6 @@ }, "apps/template/frontend/node_modules/globals": { "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", "engines": { @@ -140,25 +128,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "apps/web": { - "version": "0.1.0", - "extraneous": true, - "dependencies": { - "@repo/ui": "*", - "next": "^16.0.1", - "react": "^19.2.0", - "react-dom": "^19.2.0" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/node": "^22.15.3", - "@types/react": "19.2.2", - "@types/react-dom": "19.2.2", - "eslint": "^9.39.1", - "typescript": "5.9.2" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -215,6 +184,16 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/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/@babel/generator": { "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", @@ -249,6 +228,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/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/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -483,16 +472,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/@emnapi/runtime": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", - "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@epic-web/invariant": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", @@ -501,9 +480,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", - "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", + "integrity": "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==", "cpu": [ "ppc64" ], @@ -517,9 +496,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", - "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.1.tgz", + "integrity": "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==", "cpu": [ "arm" ], @@ -533,9 +512,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", - "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz", + "integrity": "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==", "cpu": [ "arm64" ], @@ -549,9 +528,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", - "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.1.tgz", + "integrity": "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==", "cpu": [ "x64" ], @@ -565,9 +544,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", - "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", + "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", "cpu": [ "arm64" ], @@ -581,9 +560,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", - "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz", + "integrity": "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==", "cpu": [ "x64" ], @@ -597,9 +576,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", - "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz", + "integrity": "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==", "cpu": [ "arm64" ], @@ -613,9 +592,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", - "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz", + "integrity": "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==", "cpu": [ "x64" ], @@ -629,9 +608,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", - "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz", + "integrity": "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==", "cpu": [ "arm" ], @@ -645,9 +624,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", - "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz", + "integrity": "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==", "cpu": [ "arm64" ], @@ -661,9 +640,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", - "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz", + "integrity": "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==", "cpu": [ "ia32" ], @@ -677,9 +656,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", - "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz", + "integrity": "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==", "cpu": [ "loong64" ], @@ -693,9 +672,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", - "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz", + "integrity": "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==", "cpu": [ "mips64el" ], @@ -709,9 +688,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", - "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz", + "integrity": "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==", "cpu": [ "ppc64" ], @@ -725,9 +704,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", - "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz", + "integrity": "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==", "cpu": [ "riscv64" ], @@ -741,9 +720,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", - "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz", + "integrity": "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==", "cpu": [ "s390x" ], @@ -757,9 +736,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", - "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz", + "integrity": "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==", "cpu": [ "x64" ], @@ -773,9 +752,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", - "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz", + "integrity": "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==", "cpu": [ "arm64" ], @@ -789,9 +768,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", - "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz", + "integrity": "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==", "cpu": [ "x64" ], @@ -805,9 +784,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", - "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz", + "integrity": "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==", "cpu": [ "arm64" ], @@ -821,9 +800,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", - "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz", + "integrity": "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==", "cpu": [ "x64" ], @@ -837,9 +816,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", - "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz", + "integrity": "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==", "cpu": [ "arm64" ], @@ -853,9 +832,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", - "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz", + "integrity": "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==", "cpu": [ "x64" ], @@ -869,9 +848,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", - "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz", + "integrity": "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==", "cpu": [ "arm64" ], @@ -885,9 +864,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", - "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz", + "integrity": "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==", "cpu": [ "ia32" ], @@ -901,9 +880,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", - "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz", + "integrity": "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==", "cpu": [ "x64" ], @@ -934,18 +913,6 @@ "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==", - "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", @@ -956,47 +923,55 @@ } }, "node_modules/@eslint-react/ast": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@eslint-react/ast/-/ast-2.3.5.tgz", - "integrity": "sha512-gTnLEdQ82Kcy2Yn8fLe6ks/yQx1kI3OYuWgYNb4D1XSAOYvL1Cj+UIx2/+ew9vMBLMO3NJr90EMPUr0yVOhC7w==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@eslint-react/ast/-/ast-2.3.12.tgz", + "integrity": "sha512-2wlRvqS4dxleGlL4Gp3Bh5PNb47wnAEa99CsGppzWCFXSPvm3d/bM5nJPvOwQOF53+PGa6xq1ZqwGh70zL7+zw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-react/eff": "2.3.5", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/typescript-estree": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", - "string-ts": "^2.2.1" + "@eslint-react/eff": "2.3.12", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/typescript-estree": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", + "string-ts": "^2.3.1" }, "engines": { "node": ">=20.19.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@eslint-react/core": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@eslint-react/core/-/core-2.3.5.tgz", - "integrity": "sha512-6+/3bMmkxIk4vlMwfxw4lU6y7/Z1cjGURPsooAULitbBS4+s0M0N1UjWaPpDwT4FR0SVVqjOp1yUcI66uQvQKg==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@eslint-react/core/-/core-2.3.12.tgz", + "integrity": "sha512-Q3w6f0WfVyIJriJa+tYHS4rmVQ3nwnubCH7o/VYlBCR3qczpvpvkCi2XK4clU/7vpVwHbbaXGICAbJu7tNZqoQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-react/ast": "2.3.5", - "@eslint-react/eff": "2.3.5", - "@eslint-react/shared": "2.3.5", - "@eslint-react/var": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", + "@eslint-react/ast": "2.3.12", + "@eslint-react/eff": "2.3.12", + "@eslint-react/shared": "2.3.12", + "@eslint-react/var": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", "birecord": "^0.1.1", "ts-pattern": "^5.9.0" }, "engines": { "node": ">=20.19.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@eslint-react/eff": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@eslint-react/eff/-/eff-2.3.5.tgz", - "integrity": "sha512-F2bj6v7Q1hgLn+N28pkJyYvBiTaUFh0qOEz3IXUupkqqnu9zGxmh3P7c0l//8AlR2CvRTCmSVBBhem4BhoSczw==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@eslint-react/eff/-/eff-2.3.12.tgz", + "integrity": "sha512-QjFENG1VGVrD67YFc0yiLm9zef2kTeXZGux4hlMjGLnxTHnn0tPx4T/xGzh5C1WRmolcNeIzjVWMqSngFrTphQ==", "dev": true, "license": "MIT", "engines": { @@ -1004,65 +979,73 @@ } }, "node_modules/@eslint-react/eslint-plugin": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@eslint-react/eslint-plugin/-/eslint-plugin-2.3.5.tgz", - "integrity": "sha512-5VTcKcbyDNGrpXj3y5wfYKogA8g1aVPcyupSL9/URyxLhnv14tfSNAJ64qTh0NBunETU69n7T81e4ZYJS2ctGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-react/eff": "2.3.5", - "@eslint-react/shared": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/type-utils": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", - "eslint-plugin-react-dom": "2.3.5", - "eslint-plugin-react-hooks-extra": "2.3.5", - "eslint-plugin-react-naming-convention": "2.3.5", - "eslint-plugin-react-web-api": "2.3.5", - "eslint-plugin-react-x": "2.3.5", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@eslint-react/eslint-plugin/-/eslint-plugin-2.3.12.tgz", + "integrity": "sha512-/nrnrKINpsUEWIDfy7/YT4oGMvtyMUAJy6gm1nk3YLBrW9v6SVofcOnw2k6xwmB9Zl7RExlL58amlkdRpenkzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-react/eff": "2.3.12", + "@eslint-react/shared": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/type-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", + "eslint-plugin-react-dom": "2.3.12", + "eslint-plugin-react-hooks-extra": "2.3.12", + "eslint-plugin-react-naming-convention": "2.3.12", + "eslint-plugin-react-web-api": "2.3.12", + "eslint-plugin-react-x": "2.3.12", "ts-api-utils": "^2.1.0" }, "engines": { "node": ">=20.19.0" }, "peerDependencies": { - "eslint": "^9.39.1", - "typescript": "^5.9.3" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@eslint-react/shared": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@eslint-react/shared/-/shared-2.3.5.tgz", - "integrity": "sha512-k65W/X2MeiDX21HPwtcPaFHciYVRYrzE+EZ2ok2BVQWcl24GQUEckAfdMzKQ6cS19OgjQm9k0juHjpUcyHj29g==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@eslint-react/shared/-/shared-2.3.12.tgz", + "integrity": "sha512-mIgxjEwKOknJabbQs/bxvkEhKitJnET0QDc0a89pFx36DBLJIEvdcGMCDEXFgtgjDV/WwMxIava/+coE6T3Dyw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-react/eff": "2.3.5", - "@typescript-eslint/utils": "^8.46.4", + "@eslint-react/eff": "2.3.12", + "@typescript-eslint/utils": "^8.48.1", "ts-pattern": "^5.9.0", - "zod": "^4.1.12" + "zod": "^4.1.13" }, "engines": { "node": ">=20.19.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@eslint-react/var": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@eslint-react/var/-/var-2.3.5.tgz", - "integrity": "sha512-BDq9o4kUu4h0Lvv29AY+N9LFh69tgICRNDmr5GnRmRFaYZ6/fq+UbO18K47ccb2tj2TI8V6VJFpkPx1fK7lYeQ==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@eslint-react/var/-/var-2.3.12.tgz", + "integrity": "sha512-jjgeRcop74NTzWzCF8rBN1H5avdSDLEOALJjwmYWOdxoSUNGO7OIeM/pZvHZ7G36kHDuD619P2JauCVM2/c+7A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-react/ast": "2.3.5", - "@eslint-react/eff": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", + "@eslint-react/ast": "2.3.12", + "@eslint-react/eff": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", "ts-pattern": "^5.9.0" }, "engines": { "node": ">=20.19.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@eslint/config-array": { @@ -1080,6 +1063,30 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/config-helpers": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", @@ -1107,9 +1114,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "license": "MIT", "peer": true, "dependencies": { @@ -1119,7 +1126,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -1130,6 +1137,30 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { "version": "9.39.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", @@ -1263,44 +1294,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "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/@repo/better_child_process": { "resolved": "packages/better_child_process", "link": true @@ -1313,9 +1306,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz", - "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", "cpu": [ "arm" ], @@ -1327,9 +1320,9 @@ "peer": true }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz", - "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", "cpu": [ "arm64" ], @@ -1341,9 +1334,9 @@ "peer": true }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz", - "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", "cpu": [ "arm64" ], @@ -1355,9 +1348,9 @@ "peer": true }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz", - "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", "cpu": [ "x64" ], @@ -1369,9 +1362,9 @@ "peer": true }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz", - "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", "cpu": [ "arm64" ], @@ -1383,9 +1376,9 @@ "peer": true }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz", - "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", "cpu": [ "x64" ], @@ -1397,9 +1390,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz", - "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", "cpu": [ "arm" ], @@ -1411,9 +1404,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz", - "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", "cpu": [ "arm" ], @@ -1425,9 +1418,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz", - "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", "cpu": [ "arm64" ], @@ -1439,9 +1432,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz", - "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", "cpu": [ "arm64" ], @@ -1453,9 +1446,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz", - "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", "cpu": [ "loong64" ], @@ -1467,9 +1460,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz", - "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", "cpu": [ "ppc64" ], @@ -1481,9 +1474,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz", - "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", "cpu": [ "riscv64" ], @@ -1495,9 +1488,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz", - "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", "cpu": [ "riscv64" ], @@ -1509,9 +1502,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz", - "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", "cpu": [ "s390x" ], @@ -1523,9 +1516,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz", - "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", "cpu": [ "x64" ], @@ -1537,9 +1530,9 @@ "peer": true }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz", - "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", "cpu": [ "x64" ], @@ -1551,9 +1544,9 @@ "peer": true }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz", - "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", "cpu": [ "arm64" ], @@ -1565,9 +1558,9 @@ "peer": true }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz", - "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", "cpu": [ "arm64" ], @@ -1579,9 +1572,9 @@ "peer": true }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz", - "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", "cpu": [ "ia32" ], @@ -1593,9 +1586,9 @@ "peer": true }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz", - "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", "cpu": [ "x64" ], @@ -1607,9 +1600,9 @@ "peer": true }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz", - "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", "cpu": [ "x64" ], @@ -1960,15 +1953,15 @@ "license": "MIT" }, "node_modules/@types/express": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.5.tgz", - "integrity": "sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", "dev": true, "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "^1" + "@types/serve-static": "^2" } }, "node_modules/@types/express-serve-static-core": { @@ -1998,13 +1991,6 @@ "license": "MIT", "peer": true }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "24.10.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", @@ -2015,13 +2001,6 @@ "undici-types": "~7.16.0" } }, - "node_modules/@types/node/node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "devOptional": true, - "license": "MIT" - }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -2037,19 +2016,19 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", - "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", + "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "dev": true, "license": "MIT", "dependencies": { - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { - "version": "19.2.2", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", - "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", + "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==", "dev": true, "license": "MIT", "peerDependencies": { @@ -2067,40 +2046,28 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", - "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", "dev": true, "license": "MIT", "dependencies": { "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "<1" - } - }, - "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.6", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", - "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz", - "integrity": "sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz", + "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.47.0", - "@typescript-eslint/type-utils": "8.47.0", - "@typescript-eslint/utils": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/type-utils": "8.48.1", + "@typescript-eslint/utils": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2114,7 +2081,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.47.0", + "@typescript-eslint/parser": "^8.48.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -2130,16 +2097,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.47.0.tgz", - "integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz", + "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.47.0", - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", "debug": "^4.3.4" }, "engines": { @@ -2155,14 +2122,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", - "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz", + "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.47.0", - "@typescript-eslint/types": "^8.47.0", + "@typescript-eslint/tsconfig-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", "debug": "^4.3.4" }, "engines": { @@ -2177,14 +2144,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", - "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz", + "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0" + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2195,9 +2162,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", - "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz", + "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==", "dev": true, "license": "MIT", "engines": { @@ -2212,15 +2179,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.47.0.tgz", - "integrity": "sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz", + "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0", - "@typescript-eslint/utils": "8.47.0", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/utils": "8.48.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -2237,9 +2204,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", - "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz", + "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==", "dev": true, "license": "MIT", "engines": { @@ -2251,21 +2218,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", - "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz", + "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.47.0", - "@typescript-eslint/tsconfig-utils": "8.47.0", - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0", + "@typescript-eslint/project-service": "8.48.1", + "@typescript-eslint/tsconfig-utils": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", + "tinyglobby": "^0.2.15", "ts-api-utils": "^2.1.0" }, "engines": { @@ -2279,56 +2245,17 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", - "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz", + "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.47.0", - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0" + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2343,13 +2270,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", - "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz", + "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/types": "8.48.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -2360,6 +2287,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/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/@vitejs/plugin-react": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz", @@ -2642,9 +2582,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.27", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.27.tgz", - "integrity": "sha512-2CXFpkjVnY2FT+B6GrSYxzYf65BJWEqz5tIRHCvNsZZ2F3CmsCB37h8SpYgKG7y9C4YAeTipIPWG7EmFmhAeXA==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.2.tgz", + "integrity": "sha512-PxSsosKQjI38iXkmb3d0Y32efqyA0uW4s41u4IVBsLlWLhCiYNpH/AfNOVWRqCQBlD8TFJTz6OUWNd4DFJCnmw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2672,33 +2612,37 @@ "license": "(MIT OR Apache-2.0)" }, "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", - "debug": "^4.4.0", + "debug": "^4.4.3", "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -2715,9 +2659,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", - "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -2735,11 +2679,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.25", - "caniuse-lite": "^1.0.30001754", - "electron-to-chromium": "^1.5.249", + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", - "update-browserslist-db": "^1.1.4" + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -2815,9 +2759,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "version": "1.0.30001759", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", + "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", "dev": true, "funding": [ { @@ -2925,15 +2869,16 @@ "license": "MIT" }, "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/content-type": { @@ -2970,6 +2915,19 @@ "node": ">=6.6.0" } }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cross-env": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", @@ -3003,9 +2961,9 @@ } }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true, "license": "MIT" }, @@ -3233,9 +3191,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.250", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.250.tgz", - "integrity": "sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==", + "version": "1.5.264", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.264.tgz", + "integrity": "sha512-1tEf0nLgltC3iy9wtlYDlQDc5Rg9lEKVjEmIHJ21rI9OcqkvD45K1oyNIRA4rR1z3LgJ7KeGzEBojVcV6m4qjA==", "dev": true, "license": "ISC" }, @@ -3431,9 +3389,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", - "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", + "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -3443,32 +3401,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.0", - "@esbuild/android-arm": "0.27.0", - "@esbuild/android-arm64": "0.27.0", - "@esbuild/android-x64": "0.27.0", - "@esbuild/darwin-arm64": "0.27.0", - "@esbuild/darwin-x64": "0.27.0", - "@esbuild/freebsd-arm64": "0.27.0", - "@esbuild/freebsd-x64": "0.27.0", - "@esbuild/linux-arm": "0.27.0", - "@esbuild/linux-arm64": "0.27.0", - "@esbuild/linux-ia32": "0.27.0", - "@esbuild/linux-loong64": "0.27.0", - "@esbuild/linux-mips64el": "0.27.0", - "@esbuild/linux-ppc64": "0.27.0", - "@esbuild/linux-riscv64": "0.27.0", - "@esbuild/linux-s390x": "0.27.0", - "@esbuild/linux-x64": "0.27.0", - "@esbuild/netbsd-arm64": "0.27.0", - "@esbuild/netbsd-x64": "0.27.0", - "@esbuild/openbsd-arm64": "0.27.0", - "@esbuild/openbsd-x64": "0.27.0", - "@esbuild/openharmony-arm64": "0.27.0", - "@esbuild/sunos-x64": "0.27.0", - "@esbuild/win32-arm64": "0.27.0", - "@esbuild/win32-ia32": "0.27.0", - "@esbuild/win32-x64": "0.27.0" + "@esbuild/aix-ppc64": "0.27.1", + "@esbuild/android-arm": "0.27.1", + "@esbuild/android-arm64": "0.27.1", + "@esbuild/android-x64": "0.27.1", + "@esbuild/darwin-arm64": "0.27.1", + "@esbuild/darwin-x64": "0.27.1", + "@esbuild/freebsd-arm64": "0.27.1", + "@esbuild/freebsd-x64": "0.27.1", + "@esbuild/linux-arm": "0.27.1", + "@esbuild/linux-arm64": "0.27.1", + "@esbuild/linux-ia32": "0.27.1", + "@esbuild/linux-loong64": "0.27.1", + "@esbuild/linux-mips64el": "0.27.1", + "@esbuild/linux-ppc64": "0.27.1", + "@esbuild/linux-riscv64": "0.27.1", + "@esbuild/linux-s390x": "0.27.1", + "@esbuild/linux-x64": "0.27.1", + "@esbuild/netbsd-arm64": "0.27.1", + "@esbuild/netbsd-x64": "0.27.1", + "@esbuild/openbsd-arm64": "0.27.1", + "@esbuild/openbsd-x64": "0.27.1", + "@esbuild/openharmony-arm64": "0.27.1", + "@esbuild/sunos-x64": "0.27.1", + "@esbuild/win32-arm64": "0.27.1", + "@esbuild/win32-ia32": "0.27.1", + "@esbuild/win32-x64": "0.27.1" } }, "node_modules/escalade": { @@ -3605,131 +3563,131 @@ } }, "node_modules/eslint-plugin-react-dom": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-dom/-/eslint-plugin-react-dom-2.3.5.tgz", - "integrity": "sha512-SsIF5HbsXLJcbEoFbzgabqA7DOnfGd0BhD7QzZd5tqgz4gL2j2mUGCBbQjQIE0BMbKtOihbhuceQfQ/QxoJJIg==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-dom/-/eslint-plugin-react-dom-2.3.12.tgz", + "integrity": "sha512-GBiIANlm5267Ys+xM5AH74F5kzK43N1c6pm2oy+/P+tiZUpebIgEAilFGSAoAHqyyK1ul+kYsYr5Z8k2hP6aOw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-react/ast": "2.3.5", - "@eslint-react/core": "2.3.5", - "@eslint-react/eff": "2.3.5", - "@eslint-react/shared": "2.3.5", - "@eslint-react/var": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", + "@eslint-react/ast": "2.3.12", + "@eslint-react/core": "2.3.12", + "@eslint-react/eff": "2.3.12", + "@eslint-react/shared": "2.3.12", + "@eslint-react/var": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", "compare-versions": "^6.1.1", - "string-ts": "^2.2.1", + "string-ts": "^2.3.1", "ts-pattern": "^5.9.0" }, "engines": { "node": ">=20.19.0" }, "peerDependencies": { - "eslint": "^9.39.1", - "typescript": "^5.9.3" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/eslint-plugin-react-hooks-extra": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks-extra/-/eslint-plugin-react-hooks-extra-2.3.5.tgz", - "integrity": "sha512-IxPs6O/XCpm8FAv38TyJKcHkeS/qNb97PdbH1OqHbf4BAT/QTInWweNEpePiyydQ0YuLvHqTo1dreY8Jj6Re3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-react/ast": "2.3.5", - "@eslint-react/core": "2.3.5", - "@eslint-react/eff": "2.3.5", - "@eslint-react/shared": "2.3.5", - "@eslint-react/var": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/type-utils": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", - "string-ts": "^2.2.1", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks-extra/-/eslint-plugin-react-hooks-extra-2.3.12.tgz", + "integrity": "sha512-6Dg8MMcDIGMTEguB5qanN1iERVEQIXmr7wC3hSR7pexmSASGLqer2MrM8VRa66aq28r5XmhTcNjKqh/R3Hetnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-react/ast": "2.3.12", + "@eslint-react/core": "2.3.12", + "@eslint-react/eff": "2.3.12", + "@eslint-react/shared": "2.3.12", + "@eslint-react/var": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/type-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", + "string-ts": "^2.3.1", "ts-pattern": "^5.9.0" }, "engines": { "node": ">=20.0.0" }, "peerDependencies": { - "eslint": "^9.39.1", - "typescript": "^5.9.3" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/eslint-plugin-react-naming-convention": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-naming-convention/-/eslint-plugin-react-naming-convention-2.3.5.tgz", - "integrity": "sha512-sjKvdJq90HWNYRBtwia7C/N8NXdg+k8O7ikQqf6QsOuTUHGLgFWGtxx1AktfizlSusCdb96w5LJ4MSi+KsuVZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-react/ast": "2.3.5", - "@eslint-react/core": "2.3.5", - "@eslint-react/eff": "2.3.5", - "@eslint-react/shared": "2.3.5", - "@eslint-react/var": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/type-utils": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", - "string-ts": "^2.2.1", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-naming-convention/-/eslint-plugin-react-naming-convention-2.3.12.tgz", + "integrity": "sha512-2kTupCIdJaeuf8p2QuWckjGzyA+QiIuH6+kO8dZbuMw5dNdP3oJDtDZWLgMXk+WT8mdegu5a2Q9i2QjwxMKKbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-react/ast": "2.3.12", + "@eslint-react/core": "2.3.12", + "@eslint-react/eff": "2.3.12", + "@eslint-react/shared": "2.3.12", + "@eslint-react/var": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/type-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", + "string-ts": "^2.3.1", "ts-pattern": "^5.9.0" }, "engines": { "node": ">=20.19.0" }, "peerDependencies": { - "eslint": "^9.39.1", - "typescript": "^5.9.3" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/eslint-plugin-react-web-api": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-web-api/-/eslint-plugin-react-web-api-2.3.5.tgz", - "integrity": "sha512-wY/hNWQxshTZ2niuu8QcARQuDg5w+cEA2OYtnrnPDjhy0qxikAaYA4NUx7HTAXoMC1Kxl78+NbQBBXnlwoMAZA==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-web-api/-/eslint-plugin-react-web-api-2.3.12.tgz", + "integrity": "sha512-9CWujvWbuwsBSrz2Ts4+NR996VKbDMbYv6ziHmmZLucHt3hZELF8eu5YHz99SLQeFzQynOMnZdR63ICr/dF+JA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-react/ast": "2.3.5", - "@eslint-react/core": "2.3.5", - "@eslint-react/eff": "2.3.5", - "@eslint-react/shared": "2.3.5", - "@eslint-react/var": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", - "string-ts": "^2.2.1", + "@eslint-react/ast": "2.3.12", + "@eslint-react/core": "2.3.12", + "@eslint-react/eff": "2.3.12", + "@eslint-react/shared": "2.3.12", + "@eslint-react/var": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", + "string-ts": "^2.3.1", "ts-pattern": "^5.9.0" }, "engines": { "node": ">=20.19.0" }, "peerDependencies": { - "eslint": "^9.39.1", - "typescript": "^5.9.3" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/eslint-plugin-react-x": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-x/-/eslint-plugin-react-x-2.3.5.tgz", - "integrity": "sha512-Yj+6e2ds6Gg3KRPgNdifincu3cuxDYPcboCXc5EGHC//6JZXRgtqQ3N5uP9RVHnCHmKF2EiZ76XyPDnp4hMgEg==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-x/-/eslint-plugin-react-x-2.3.12.tgz", + "integrity": "sha512-G9ThX5LZQun3243JN/UchMbGPra9ZL1D7Wi4dwaIgqh26nRK8W6LBqRTJC+jlrmOanosg+flcxpUyFS/N+Ch7A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-react/ast": "2.3.5", - "@eslint-react/core": "2.3.5", - "@eslint-react/eff": "2.3.5", - "@eslint-react/shared": "2.3.5", - "@eslint-react/var": "2.3.5", - "@typescript-eslint/scope-manager": "^8.46.4", - "@typescript-eslint/type-utils": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", - "@typescript-eslint/utils": "^8.46.4", + "@eslint-react/ast": "2.3.12", + "@eslint-react/core": "2.3.12", + "@eslint-react/eff": "2.3.12", + "@eslint-react/shared": "2.3.12", + "@eslint-react/var": "2.3.12", + "@typescript-eslint/scope-manager": "^8.48.1", + "@typescript-eslint/type-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "@typescript-eslint/utils": "^8.48.1", "compare-versions": "^6.1.1", "is-immutable-type": "^5.0.1", - "string-ts": "^2.2.1", + "string-ts": "^2.3.1", "ts-api-utils": "^2.1.0", "ts-pattern": "^5.9.0" }, @@ -3737,8 +3695,39 @@ "node": ">=20.19.0" }, "peerDependencies": { - "eslint": "^9.39.1", - "typescript": "^5.9.3" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, "node_modules/eslint-scope": { @@ -3759,10 +3748,34 @@ } }, "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==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/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==", "license": "Apache-2.0", + "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -3770,6 +3783,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -3788,6 +3814,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/espree/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==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", @@ -3842,18 +3881,19 @@ } }, "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "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.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", @@ -3890,36 +3930,6 @@ "license": "MIT", "peer": true }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "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.8" - }, - "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", @@ -3934,16 +3944,6 @@ "license": "MIT", "peer": true }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "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", @@ -3971,9 +3971,9 @@ } }, "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "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", @@ -3984,7 +3984,11 @@ "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/find-up": { @@ -4048,6 +4052,13 @@ "node": ">= 0.6" } }, + "node_modules/fp-ts": { + "version": "2.16.11", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.11.tgz", + "integrity": "sha512-LaI+KaX2NFkfn1ZGHoKCmcfv7yrZsC3b8NtWsTVQeHkq4F27vI5igUuO53sxqDEa2gNQMHFPmpojDw/1zmUK7w==", + "license": "MIT", + "peer": true + }, "node_modules/fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", @@ -4349,28 +4360,23 @@ } }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "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.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/http-status-codes": { @@ -4380,15 +4386,19 @@ "license": "MIT" }, "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "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": { @@ -4455,6 +4465,15 @@ "node": ">= 0.4" } }, + "node_modules/io-ts": { + "version": "2.2.22", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.22.tgz", + "integrity": "sha512-FHCCztTkHoV9mdBsHpocLpdTAfh956ZQcIkWQxxS0U5HT53vtrcuYdQneEJKH6xILaLNzXVl2Cvwtoy8XNN0AA==", + "license": "MIT", + "peerDependencies": { + "fp-ts": "^2.5.0" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5342,30 +5361,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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", @@ -5376,27 +5371,35 @@ } }, "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "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": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -5483,6 +5486,17 @@ "url": "https://opencollective.com/nodemon" } }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/nodemon/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -5493,17 +5507,17 @@ "node": ">=4" } }, - "node_modules/nodemon/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "node_modules/nodemon/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" } }, "node_modules/nodemon/node_modules/supports-color": { @@ -5791,6 +5805,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playoff-schedule-backend": { + "resolved": "apps/playoff-schedule/backend", + "link": true + }, + "node_modules/playoff-schedule-frontend": { + "resolved": "apps/playoff-schedule/frontend", + "link": true + }, "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", @@ -5800,6 +5822,34 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5811,9 +5861,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, "license": "MIT", "bin": { @@ -5891,27 +5941,6 @@ "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", @@ -5922,55 +5951,39 @@ } }, "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "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.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.10" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "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/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", - "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", + "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", - "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", + "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.0" + "react": "^19.2.1" } }, "node_modules/react-is": { @@ -6089,21 +6102,10 @@ "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/rollup": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", - "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -6116,28 +6118,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.2", - "@rollup/rollup-android-arm64": "4.53.2", - "@rollup/rollup-darwin-arm64": "4.53.2", - "@rollup/rollup-darwin-x64": "4.53.2", - "@rollup/rollup-freebsd-arm64": "4.53.2", - "@rollup/rollup-freebsd-x64": "4.53.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", - "@rollup/rollup-linux-arm-musleabihf": "4.53.2", - "@rollup/rollup-linux-arm64-gnu": "4.53.2", - "@rollup/rollup-linux-arm64-musl": "4.53.2", - "@rollup/rollup-linux-loong64-gnu": "4.53.2", - "@rollup/rollup-linux-ppc64-gnu": "4.53.2", - "@rollup/rollup-linux-riscv64-gnu": "4.53.2", - "@rollup/rollup-linux-riscv64-musl": "4.53.2", - "@rollup/rollup-linux-s390x-gnu": "4.53.2", - "@rollup/rollup-linux-x64-gnu": "4.53.2", - "@rollup/rollup-linux-x64-musl": "4.53.2", - "@rollup/rollup-openharmony-arm64": "4.53.2", - "@rollup/rollup-win32-arm64-msvc": "4.53.2", - "@rollup/rollup-win32-ia32-msvc": "4.53.2", - "@rollup/rollup-win32-x64-gnu": "4.53.2", - "@rollup/rollup-win32-x64-msvc": "4.53.2", + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" } }, @@ -6157,30 +6159,6 @@ "node": ">= 18" } }, - "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.3", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", @@ -6200,26 +6178,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -6266,12 +6224,16 @@ "license": "MIT" }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { @@ -6469,19 +6431,6 @@ "node": ">=10" } }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6514,9 +6463,9 @@ } }, "node_modules/string-ts": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/string-ts/-/string-ts-2.2.1.tgz", - "integrity": "sha512-Q2u0gko67PLLhbte5HmPfdOjNvUKbKQM+mCNQae6jE91DmoFHY6HH9GcdqCeNx87DZ2KKjiFxmA0R/42OneGWw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/string-ts/-/string-ts-2.3.1.tgz", + "integrity": "sha512-xSJq+BS52SaFFAVxuStmx6n5aYZU571uYUnUrPXkPFCfdHyZMMlbP2v2Wx5sNBnAVzq/2+0+mcBLBa3Xa5ubYw==", "dev": true, "license": "MIT" }, @@ -6810,13 +6759,6 @@ "dev": true, "license": "MIT" }, - "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", - "optional": true - }, "node_modules/tsx": { "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", @@ -6837,27 +6779,27 @@ } }, "node_modules/turbo": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.6.1.tgz", - "integrity": "sha512-qBwXXuDT3rA53kbNafGbT5r++BrhRgx3sAo0cHoDAeG9g1ItTmUMgltz3Hy7Hazy1ODqNpR+C7QwqL6DYB52yA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.6.3.tgz", + "integrity": "sha512-bf6YKUv11l5Xfcmg76PyWoy/e2vbkkxFNBGJSnfdSXQC33ZiUfutYh6IXidc5MhsnrFkWfdNNLyaRk+kHMLlwA==", "dev": true, "license": "MIT", "bin": { "turbo": "bin/turbo" }, "optionalDependencies": { - "turbo-darwin-64": "2.6.1", - "turbo-darwin-arm64": "2.6.1", - "turbo-linux-64": "2.6.1", - "turbo-linux-arm64": "2.6.1", - "turbo-windows-64": "2.6.1", - "turbo-windows-arm64": "2.6.1" + "turbo-darwin-64": "2.6.3", + "turbo-darwin-arm64": "2.6.3", + "turbo-linux-64": "2.6.3", + "turbo-linux-arm64": "2.6.3", + "turbo-windows-64": "2.6.3", + "turbo-windows-arm64": "2.6.3" } }, "node_modules/turbo-darwin-64": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.6.1.tgz", - "integrity": "sha512-Dm0HwhyZF4J0uLqkhUyCVJvKM9Rw7M03v3J9A7drHDQW0qAbIGBrUijQ8g4Q9Cciw/BXRRd8Uzkc3oue+qn+ZQ==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.6.3.tgz", + "integrity": "sha512-BlJJDc1CQ7SK5Y5qnl7AzpkvKSnpkfPmnA+HeU/sgny3oHZckPV2776ebO2M33CYDSor7+8HQwaodY++IINhYg==", "cpu": [ "x64" ], @@ -6869,9 +6811,9 @@ ] }, "node_modules/turbo-darwin-arm64": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.6.1.tgz", - "integrity": "sha512-U0PIPTPyxdLsrC3jN7jaJUwgzX5sVUBsKLO7+6AL+OASaa1NbT1pPdiZoTkblBAALLP76FM0LlnsVQOnmjYhyw==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.6.3.tgz", + "integrity": "sha512-MwVt7rBKiOK7zdYerenfCRTypefw4kZCue35IJga9CH1+S50+KTiCkT6LBqo0hHeoH2iKuI0ldTF2a0aB72z3w==", "cpu": [ "arm64" ], @@ -6883,9 +6825,9 @@ ] }, "node_modules/turbo-linux-64": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.6.1.tgz", - "integrity": "sha512-eM1uLWgzv89bxlK29qwQEr9xYWBhmO/EGiH22UGfq+uXr+QW1OvNKKMogSN65Ry8lElMH4LZh0aX2DEc7eC0Mw==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.6.3.tgz", + "integrity": "sha512-cqpcw+dXxbnPtNnzeeSyWprjmuFVpHJqKcs7Jym5oXlu/ZcovEASUIUZVN3OGEM6Y/OTyyw0z09tOHNt5yBAVg==", "cpu": [ "x64" ], @@ -6897,9 +6839,9 @@ ] }, "node_modules/turbo-linux-arm64": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.6.1.tgz", - "integrity": "sha512-MFFh7AxAQAycXKuZDrbeutfWM5Ep0CEZ9u7zs4Hn2FvOViTCzIfEhmuJou3/a5+q5VX1zTxQrKGy+4Lf5cdpsA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.6.3.tgz", + "integrity": "sha512-MterpZQmjXyr4uM7zOgFSFL3oRdNKeflY7nsjxJb2TklsYqiu3Z9pQ4zRVFFH8n0mLGna7MbQMZuKoWqqHb45w==", "cpu": [ "arm64" ], @@ -6911,9 +6853,9 @@ ] }, "node_modules/turbo-windows-64": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.6.1.tgz", - "integrity": "sha512-buq7/VAN7KOjMYi4tSZT5m+jpqyhbRU2EUTTvp6V0Ii8dAkY2tAAjQN1q5q2ByflYWKecbQNTqxmVploE0LVwQ==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.6.3.tgz", + "integrity": "sha512-biDU70v9dLwnBdLf+daoDlNJVvqOOP8YEjqNipBHzgclbQlXbsi6Gqqelp5er81Qo3BiRgmTNx79oaZQTPb07Q==", "cpu": [ "x64" ], @@ -6925,9 +6867,9 @@ ] }, "node_modules/turbo-windows-arm64": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.6.1.tgz", - "integrity": "sha512-7w+AD5vJp3R+FB0YOj1YJcNcOOvBior7bcHTodqp90S3x3bLgpr7tE6xOea1e8JkP7GK6ciKVUpQvV7psiwU5Q==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.6.3.tgz", + "integrity": "sha512-dDHVKpSeukah3VsI/xMEKeTnV9V9cjlpFSUs4bmsUiLu3Yv2ENlgVEZv65wxbeE0bh0jjpmElDT+P1KaCxArQQ==", "cpu": [ "arm64" ], @@ -7054,16 +6996,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.47.0.tgz", - "integrity": "sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==", + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz", + "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.47.0", - "@typescript-eslint/parser": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0", - "@typescript-eslint/utils": "8.47.0" + "@typescript-eslint/eslint-plugin": "8.48.1", + "@typescript-eslint/parser": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/utils": "8.48.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7102,6 +7044,13 @@ "dev": true, "license": "MIT" }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7112,9 +7061,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", - "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", "dev": true, "funding": [ { @@ -7162,9 +7111,9 @@ } }, "node_modules/vite": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz", - "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", + "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -7747,34 +7696,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vite/node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7911,9 +7832,9 @@ } }, "node_modules/zod": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", - "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "dev": true, "license": "MIT", "funding": { @@ -7927,53 +7848,6 @@ "packages/common": { "version": "1.0.0", "license": "ISC" - }, - "packages/config-env": { - "name": "@repo/config-env", - "version": "0.0.0", - "extraneous": true - }, - "packages/eslint-config": { - "name": "@repo/eslint-config", - "version": "0.0.0", - "extraneous": true, - "devDependencies": { - "@eslint/js": "^9.39.1", - "@next/eslint-plugin-next": "^15.5.0", - "eslint": "^9.39.1", - "eslint-config-prettier": "^10.1.1", - "eslint-plugin-only-warn": "^1.1.0", - "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-turbo": "^2.6.0", - "globals": "^16.5.0", - "typescript": "^5.9.2", - "typescript-eslint": "^8.46.3" - } - }, - "packages/typescript-config": { - "name": "@repo/typescript-config", - "version": "0.0.0", - "extraneous": true, - "license": "MIT" - }, - "packages/ui": { - "name": "@repo/ui", - "version": "0.0.0", - "extraneous": true, - "dependencies": { - "react": "^19.2.0", - "react-dom": "^19.2.0" - }, - "devDependencies": { - "@repo/eslint-config": "*", - "@repo/typescript-config": "*", - "@types/node": "^22.15.3", - "@types/react": "19.2.2", - "@types/react-dom": "19.2.2", - "eslint": "^9.39.1", - "typescript": "5.9.2" - } } } } diff --git a/package.json b/package.json index 35155bd..b671b51 100644 --- a/package.json +++ b/package.json @@ -37,12 +37,15 @@ ], "dependencies": { "@tailwindcss/vite": "^4.1.17", + "cors": "^2.8.5", "dotenv": "^17.2.3", "dotenv-cli": "^11.0.0", "eslint-plugin-bsd": "^1.0.0", "eslint-plugin-react": "^7.37.5", "express": "^5.1.0", "http-status-codes": "^2.3.0", + "io-ts": "^2.2.22", + "react": "^19.2.1", "tailwindcss": "^4.1.17", "tsx": "^4.21.0" } diff --git a/turbo.json b/turbo.json index 72419fe..fb6ab51 100644 --- a/turbo.json +++ b/turbo.json @@ -1,7 +1,7 @@ { "$schema": "https://turborepo.com/schema.json", "ui": "tui", - "globalPassThroughEnv": ["FRONTEND_PORT","BACKEND_PORT","NODE_ENV"], + "globalPassThroughEnv": ["FRONTEND_PORT","BACKEND_PORT","NODE_ENV","TBA_API_KEY"], "tasks": { "build": {