Merge pull request #48 from VAR-Virtual-Air-Rescue/eslint

Fix NextJS app ESlint errors
This commit was merged in pull request #48.
This commit is contained in:
PxlLoewe
2025-07-10 00:37:12 -07:00
committed by GitHub
89 changed files with 845 additions and 432 deletions

View File

@@ -2,6 +2,7 @@
"editor.formatOnSave": true, "editor.formatOnSave": true,
"files.autoSave": "off", "files.autoSave": "off",
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.workingDirectories": [{ "mode": "auto" }],
"editor.codeActionsOnSave": ["source.formatDocument", "source.fixAll.eslint"], "editor.codeActionsOnSave": ["source.formatDocument", "source.fixAll.eslint"],
"typescript.validate.enable": true, "typescript.validate.enable": true,
"typescript.tsserver.experimental.enableProjectDiagnostics": true, "typescript.tsserver.experimental.enableProjectDiagnostics": true,

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { HpgState } from "@repo/db"; import { HpgState } from "@repo/db";
import { cn } from "@repo/shared-components"; import { cn } from "@repo/shared-components";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
@@ -6,7 +7,6 @@ import { getConnectedAircraftsAPI } from "_querys/aircrafts";
import { getStationsAPI } from "_querys/stations"; import { getStationsAPI } from "_querys/stations";
import { Ambulance, FireExtinguisher, Radio, Siren } from "lucide-react"; import { Ambulance, FireExtinguisher, Radio, Siren } from "lucide-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { FieldValues } from "react-hook-form";
type MissionStationsSelectProps = { type MissionStationsSelectProps = {
selectedStations?: number[]; selectedStations?: number[];
@@ -54,7 +54,6 @@ export function StationsSelect({
...(vehicleStates.hpgFireEngineState !== HpgState.NOT_REQUESTED || undefined ? ["FW"] : []), ...(vehicleStates.hpgFireEngineState !== HpgState.NOT_REQUESTED || undefined ? ["FW"] : []),
...(vehicleStates.hpgPoliceState !== HpgState.NOT_REQUESTED || undefined ? ["POL"] : []), ...(vehicleStates.hpgPoliceState !== HpgState.NOT_REQUESTED || undefined ? ["POL"] : []),
]); ]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedStations, vehicleStates]); }, [selectedStations, vehicleStates]);
// Helper to check if a station is a vehicle and its state is NOT_REQUESTED // Helper to check if a station is a vehicle and its state is NOT_REQUESTED

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
"use client"; "use client";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { useDispatchConnectionStore } from "../../../../../_store/dispatch/connectionStore"; import { useDispatchConnectionStore } from "../../../../../_store/dispatch/connectionStore";
@@ -22,7 +23,6 @@ export const ConnectionBtn = () => {
const [logoffDebounce, setLogoffDebounce] = useState<NodeJS.Timeout | null>(null); const [logoffDebounce, setLogoffDebounce] = useState<NodeJS.Timeout | null>(null);
const session = useSession(); const session = useSession();
const uid = session.data?.user?.id; const uid = session.data?.user?.id;
if (!uid) return null;
// useEffect für die Logoff-Zeit // useEffect für die Logoff-Zeit
const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || []; const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || [];
@@ -58,7 +58,7 @@ export const ConnectionBtn = () => {
connection.disconnect(); connection.disconnect();
}; };
}, [connection.disconnect]); }, [connection.disconnect]);
if (!uid) return null;
return ( return (
<div className="rounded-box bg-base-200 flex justify-center items-center gap-2 p-1"> <div className="rounded-box bg-base-200 flex justify-center items-center gap-2 p-1">
{connection.message.length > 0 && ( {connection.message.length > 0 && (

View File

@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client"; "use client";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { BellRing, BookmarkPlus, Radio } from "lucide-react"; import { BellRing, BookmarkPlus } from "lucide-react";
import { KEYWORD_CATEGORY, Mission, missionType, Prisma } from "@repo/db"; import { KEYWORD_CATEGORY, Mission, missionType, Prisma } from "@repo/db";
import { import {
JsonValueType, JsonValueType,

View File

@@ -26,7 +26,14 @@ export const Pannel = () => {
setOpen(false); setOpen(false);
} }
} }
}, [missions, setMissionFormValues, setEditingMission, setOpen, missionFormValues]); }, [
missions,
setMissionFormValues,
setEditingMission,
setOpen,
missionFormValues,
editingMissionId,
]);
return ( return (
<div className={cn("flex-1 max-w-[600px] z-9999999")}> <div className={cn("flex-1 max-w-[600px] z-9999999")}>

View File

@@ -1,4 +1,4 @@
import { ConnectedAircraft, Prisma } from "@repo/db"; import { Prisma } from "@repo/db";
import { usePilotConnectionStore } from "_store/pilot/connectionStore"; import { usePilotConnectionStore } from "_store/pilot/connectionStore";
import { useMrtStore } from "_store/pilot/MrtStore"; import { useMrtStore } from "_store/pilot/MrtStore";
import { pilotSocket } from "(app)/pilot/socket"; import { pilotSocket } from "(app)/pilot/socket";
@@ -21,7 +21,7 @@ export const useButtons = () => {
}) => editConnectedAircraftAPI(aircraftId, data), }) => editConnectedAircraftAPI(aircraftId, data),
}); });
const { page, setPage } = useMrtStore((state) => state); const { setPage } = useMrtStore((state) => state);
const handleButton = const handleButton =
(button: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0" | "home") => () => { (button: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0" | "home") => () => {

View File

@@ -9,7 +9,6 @@ import { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/airc
import { Prisma } from "@repo/db"; import { Prisma } from "@repo/db";
import { getNextDateWithTime } from "@repo/shared-components"; import { getNextDateWithTime } from "@repo/shared-components";
import { Select } from "_components/Select"; import { Select } from "_components/Select";
import { components } from "react-select";
import { Radio } from "lucide-react"; import { Radio } from "lucide-react";
export const ConnectionBtn = () => { export const ConnectionBtn = () => {
@@ -54,7 +53,7 @@ export const ConnectionBtn = () => {
return () => { return () => {
connection.disconnect(); connection.disconnect();
}; };
}, [connection.disconnect]); }, [connection, connection.disconnect]);
const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || []; const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || [];
@@ -87,7 +86,7 @@ export const ConnectionBtn = () => {
return () => { return () => {
if (logoffDebounce) clearTimeout(logoffDebounce); if (logoffDebounce) clearTimeout(logoffDebounce);
}; };
}, [logoffHours, logoffMinutes, connection.connectedAircraft]); }, [logoffHours, logoffMinutes, connection.connectedAircraft, aircraftMutation, logoffDebounce]);
const session = useSession(); const session = useSession();
const uid = session.data?.user?.id; const uid = session.data?.user?.id;
@@ -143,7 +142,9 @@ export const ConnectionBtn = () => {
}) })
} }
value={form.selectedStationId ?? ""} value={form.selectedStationId ?? ""}
formatOptionLabel={(option: any) => option.component} formatOptionLabel={(option: unknown) =>
(option as { component: React.ReactNode }).component
}
options={ options={
stations?.map((station) => ({ stations?.map((station) => ({
value: station.id.toString(), value: station.id.toString(),

View File

@@ -8,7 +8,7 @@ import dynamic from "next/dynamic";
import { ConnectedDispatcher } from "tracker/_components/ConnectedDispatcher"; import { ConnectedDispatcher } from "tracker/_components/ConnectedDispatcher";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { usePilotConnectionStore } from "_store/pilot/connectionStore"; import { usePilotConnectionStore } from "_store/pilot/connectionStore";
import { getAircraftsAPI, getConnectedAircraftsAPI } from "_querys/aircrafts"; import { getAircraftsAPI } from "_querys/aircrafts";
import { checkSimulatorConnected } from "@repo/shared-components"; import { checkSimulatorConnected } from "@repo/shared-components";
import { SimConnectionAlert } from "(app)/pilot/_components/SimConnectionAlert"; import { SimConnectionAlert } from "(app)/pilot/_components/SimConnectionAlert";

View File

@@ -1,5 +1,4 @@
import { NextPage } from "next"; import { NextPage } from "next";
import { ReactNode } from "react";
const AuthLayout: NextPage< const AuthLayout: NextPage<
Readonly<{ Readonly<{

View File

@@ -14,7 +14,7 @@ export const Login = () => {
if (status === "authenticated") { if (status === "authenticated") {
navigate.push("/"); navigate.push("/");
} }
}, [session, navigate]); }, [session, navigate, status]);
useEffect(() => { useEffect(() => {
const signInWithCode = async () => { const signInWithCode = async () => {

View File

@@ -1,5 +1,5 @@
"use client"; "use client";
import { useDebounce } from "_helpers/useDebounce"; import { useDebounce } from "@repo/shared-components";
import { useAudioStore } from "_store/audioStore"; import { useAudioStore } from "_store/audioStore";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
@@ -112,5 +112,6 @@ export const useSounds = ({
callToLong.current!.pause(); callToLong.current!.pause();
}; };
} }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isTransmitting]); }, [isTransmitting]);
}; };

View File

@@ -11,10 +11,10 @@ export const CustomErrorBoundary = ({ children }: { children?: React.ReactNode }
let errorTest; let errorTest;
let errorCode = 500; let errorCode = 500;
if ("statusCode" in error) { if ("statusCode" in error) {
errorCode = (error as any).statusCode; errorCode = error.statusCode;
} }
if ("message" in error || error instanceof Error) { if ("message" in error || error instanceof Error) {
errorTest = (error as any).message; errorTest = error.message;
} else if (typeof error === "string") { } else if (typeof error === "string") {
errorTest = error; errorTest = error;
} else { } else {

View File

@@ -2,10 +2,10 @@
"use client"; "use client";
import { toast } from "react-hot-toast"; import { toast } from "react-hot-toast";
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactNode, useEffect, useState } from "react"; import { ReactNode, useEffect, useState } from "react";
import { dispatchSocket } from "(app)/dispatch/socket"; import { dispatchSocket } from "(app)/dispatch/socket";
import { Mission, NotificationPayload } from "@repo/db"; import { NotificationPayload } from "@repo/db";
import { HPGnotificationToast } from "_components/customToasts/HPGnotification"; import { HPGnotificationToast } from "_components/customToasts/HPGnotification";
import { useMapStore } from "_store/mapStore"; import { useMapStore } from "_store/mapStore";
import { AdminMessageToast } from "_components/customToasts/AdminMessage"; import { AdminMessageToast } from "_components/customToasts/AdminMessage";
@@ -30,7 +30,7 @@ export function QueryProvider({ children }: { children: ReactNode }) {
}), }),
); );
useEffect(() => { useEffect(() => {
const invalidateMission = (mission: Mission) => { const invalidateMission = () => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ["missions"], queryKey: ["missions"],
}); });

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client"; "use client";
import { FieldValues, Path } from "react-hook-form";
import SelectTemplate, { Props as SelectTemplateProps, StylesConfig } from "react-select"; import SelectTemplate, { Props as SelectTemplateProps, StylesConfig } from "react-select";
import { cn } from "@repo/shared-components"; import { cn } from "@repo/shared-components";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
@@ -99,7 +99,7 @@ const SelectCom = ({
); );
}; };
const SelectWrapper = <T extends FieldValues>(props: SelectProps) => <SelectCom {...props} />; const SelectWrapper = (props: SelectProps) => <SelectCom {...props} />;
export const Select = dynamic(() => Promise.resolve(SelectWrapper), { export const Select = dynamic(() => Promise.resolve(SelectWrapper), {
ssr: false, ssr: false,

View File

@@ -1,6 +1,6 @@
import { NotificationPayload, ValidationFailed, ValidationSuccess } from "@repo/db"; import { ValidationFailed, ValidationSuccess } from "@repo/db";
import { BaseNotification } from "_components/customToasts/BaseNotification"; import { BaseNotification } from "_components/customToasts/BaseNotification";
import { MapStore, useMapStore } from "_store/mapStore"; import { MapStore } from "_store/mapStore";
import { Check, Cross } from "lucide-react"; import { Check, Cross } from "lucide-react";
import toast, { Toast } from "react-hot-toast"; import toast, { Toast } from "react-hot-toast";

View File

@@ -5,7 +5,6 @@ import { FMS_STATUS_COLORS } from "_helpers/fmsStatusColors";
import { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/aircrafts"; import { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/aircrafts";
import { getStationsAPI } from "_querys/stations"; import { getStationsAPI } from "_querys/stations";
import { useMapStore } from "_store/mapStore"; import { useMapStore } from "_store/mapStore";
import { cpSync } from "fs";
import { X } from "lucide-react"; import { X } from "lucide-react";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { Toast, toast } from "react-hot-toast"; import { Toast, toast } from "react-hot-toast";
@@ -67,7 +66,7 @@ export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) =>
} else if (event.status == connectedAircraft?.fmsStatus && !aircraftDataAcurate) { } else if (event.status == connectedAircraft?.fmsStatus && !aircraftDataAcurate) {
setAircraftDataAccurate(true); setAircraftDataAccurate(true);
} }
}, [connectedAircraft, station]); }, [aircraftDataAcurate, connectedAircraft, event.status, t.id]);
useEffect(() => { useEffect(() => {
let soundRef: React.RefObject<HTMLAudioElement | null> | null = null; let soundRef: React.RefObject<HTMLAudioElement | null> | null = null;

View File

@@ -41,7 +41,7 @@ export const Chat = () => {
useEffect(() => { useEffect(() => {
if (!session.data?.user.id) return; if (!session.data?.user.id) return;
setOwnId(session.data?.user.id); setOwnId(session.data?.user.id);
}, [session.data?.user.id]); }, [session.data?.user.id, setOwnId]);
const filteredDispatcher = dispatcher?.filter((d) => d.userId !== session.data?.user.id); const filteredDispatcher = dispatcher?.filter((d) => d.userId !== session.data?.user.id);
const filteredAircrafts = aircrafts?.filter((a) => a.userId !== session.data?.user.id); const filteredAircrafts = aircrafts?.filter((a) => a.userId !== session.data?.user.id);
@@ -118,7 +118,7 @@ export const Chat = () => {
const dispatcherUser = dispatcher?.find((d) => d.userId === addTabValue); const dispatcherUser = dispatcher?.find((d) => d.userId === addTabValue);
const user = aircraftUser || dispatcherUser; const user = aircraftUser || dispatcherUser;
if (!user) return; if (!user) return;
let role = "Station" in user ? user.Station.bosCallsignShort : user.zone; const role = "Station" in user ? user.Station.bosCallsignShort : user.zone;
addChat(addTabValue, `${asPublicUser(user.publicUser).fullName} (${role})`); addChat(addTabValue, `${asPublicUser(user.publicUser).fullName} (${role})`);
setSelectedChat(addTabValue); setSelectedChat(addTabValue);
}} }}

View File

@@ -4,7 +4,7 @@ import { cn } from "@repo/shared-components";
import { ListCollapse, Plane } from "lucide-react"; import { ListCollapse, Plane } from "lucide-react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { getMissionsAPI } from "_querys/missions"; import { getMissionsAPI } from "_querys/missions";
import { Station } from "@repo/db"; import { Mission, Station } from "@repo/db";
import { getConnectedAircraftsAPI } from "_querys/aircrafts"; import { getConnectedAircraftsAPI } from "_querys/aircrafts";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors"; import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import { useMapStore } from "_store/mapStore"; import { useMapStore } from "_store/mapStore";
@@ -20,7 +20,13 @@ export const SituationBoard = () => {
const { data: missions } = useQuery({ const { data: missions } = useQuery({
queryKey: ["missions", "missions-on-stations"], queryKey: ["missions", "missions-on-stations"],
queryFn: () => queryFn: () =>
getMissionsAPI( getMissionsAPI<
Mission & {
MissionsOnStations: (Station & {
Station: Station;
})[];
}
>(
{ {
state: { state: {
not: "finished", not: "finished",
@@ -125,8 +131,8 @@ export const SituationBoard = () => {
<td>{mission.missionKeywordAbbreviation}</td> <td>{mission.missionKeywordAbbreviation}</td>
<td>{mission.addressCity}</td> <td>{mission.addressCity}</td>
<td> <td>
{(mission as any).MissionsOnStations?.map( {mission.MissionsOnStations?.map(
(mos: { Station: Station }) => mos.Station?.bosCallsignShort, (mos) => mos.Station?.bosCallsignShort,
).join(", ")} ).join(", ")}
</td> </td>
</tr> </tr>

View File

@@ -262,7 +262,7 @@ const AircraftMarker = ({ aircraft }: { aircraft: ConnectedAircraft & { Station:
return () => { return () => {
marker?.off("click", handleClick); marker?.off("click", handleClick);
}; };
}, [aircraft.id, openAircraftMarker, setOpenAircraftMarker, markerRef.current]); }, [aircraft.id, openAircraftMarker, setOpenAircraftMarker]);
const [anchor, setAnchor] = useState<"topleft" | "topright" | "bottomleft" | "bottomright">( const [anchor, setAnchor] = useState<"topleft" | "topright" | "bottomleft" | "bottomright">(
"topleft", "topleft",

View File

@@ -1,7 +1,6 @@
"use client"; "use client";
import { usePannelStore } from "_store/pannelStore";
import { Control, Icon, LatLngExpression } from "leaflet"; import { Control, Icon, LatLngExpression } from "leaflet";
import { useEffect, useMemo, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { import {
LayerGroup, LayerGroup,
LayersControl, LayersControl,
@@ -15,7 +14,7 @@ import {
Marker, Marker,
Tooltip, Tooltip,
} from "react-leaflet"; } from "react-leaflet";
// @ts-ignore // @ts-expect-error geojson hat keine Typen
import type { FeatureCollection, Geometry } from "geojson"; import type { FeatureCollection, Geometry } from "geojson";
import L from "leaflet"; import L from "leaflet";
import LEITSTELLENBERECHE from "./_geojson/Leitstellen.json"; import LEITSTELLENBERECHE from "./_geojson/Leitstellen.json";
@@ -197,7 +196,7 @@ const StationsLayer = ({ attribution }: { attribution: Control.Attribution }) =>
); );
}; };
const EsriSatellite = ({ attribution }: { attribution: Control.Attribution }) => { const EsriSatellite = () => {
const accessToken = process.env.NEXT_PUBLIC_ESRI_ACCESS; const accessToken = process.env.NEXT_PUBLIC_ESRI_ACCESS;
return ( return (
<> <>
@@ -221,8 +220,7 @@ const StrassentexteEsri = () => {
); );
}; };
const OpenAIP = ({ attribution }: { attribution: Control.Attribution }) => { const OpenAIP = () => {
const accessToken = process.env.NEXT_PUBLIC_OPENAIP_ACCESS;
const ref = useRef<L.TileLayer | null>(null); const ref = useRef<L.TileLayer | null>(null);
return ( return (
@@ -241,7 +239,7 @@ const OpenAIP = ({ attribution }: { attribution: Control.Attribution }) => {
); );
}; };
const NiederschlagOverlay = ({ attribution }: { attribution: Control.Attribution }) => { const NiederschlagOverlay = () => {
const tileLayerRef = useRef<L.TileLayer.WMS | null>(null); const tileLayerRef = useRef<L.TileLayer.WMS | null>(null);
return ( return (
@@ -311,7 +309,7 @@ export const BaseMaps = () => {
<RadioAreaLayer /> <RadioAreaLayer />
</LayersControl.Overlay> </LayersControl.Overlay>
<LayersControl.Overlay name={"Niederschlag"}> <LayersControl.Overlay name={"Niederschlag"}>
<NiederschlagOverlay attribution={map.attributionControl} /> <NiederschlagOverlay />
</LayersControl.Overlay> </LayersControl.Overlay>
<LayersControl.Overlay name={"Windkraftanlagen offshore"}> <LayersControl.Overlay name={"Windkraftanlagen offshore"}>
@@ -322,7 +320,7 @@ export const BaseMaps = () => {
<StationsLayer attribution={map.attributionControl} /> <StationsLayer attribution={map.attributionControl} />
</LayersControl.Overlay> </LayersControl.Overlay>
<LayersControl.Overlay name={"OpenAIP"}> <LayersControl.Overlay name={"OpenAIP"}>
<OpenAIP attribution={map.attributionControl} /> <OpenAIP />
</LayersControl.Overlay> </LayersControl.Overlay>
<LayersControl.BaseLayer name="OpenStreetMap Dark" checked> <LayersControl.BaseLayer name="OpenStreetMap Dark" checked>
@@ -348,7 +346,7 @@ export const BaseMaps = () => {
</LayersControl.BaseLayer> </LayersControl.BaseLayer>
<LayersControl.BaseLayer name="ESRI Satellite"> <LayersControl.BaseLayer name="ESRI Satellite">
<LayerGroup> <LayerGroup>
<EsriSatellite attribution={map.attributionControl} /> <EsriSatellite />
<StrassentexteEsri /> <StrassentexteEsri />
</LayerGroup> </LayerGroup>
</LayersControl.BaseLayer> </LayersControl.BaseLayer>

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import { OSMWay, Prisma } from "@repo/db"; import { OSMWay } from "@repo/db";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore"; import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
import { useMapStore } from "_store/mapStore"; import { useMapStore } from "_store/mapStore";
import { usePannelStore } from "_store/pannelStore"; import { usePannelStore } from "_store/pannelStore";
@@ -8,8 +8,6 @@ import { getOsmAddress } from "_querys/osm";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { Popup, useMap } from "react-leaflet"; import { Popup, useMap } from "react-leaflet";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { editMissionAPI } from "_querys/missions";
import { findClosestPolygon } from "_helpers/findClosestPolygon"; import { findClosestPolygon } from "_helpers/findClosestPolygon";
export const ContextMenu = () => { export const ContextMenu = () => {
@@ -22,8 +20,9 @@ export const ContextMenu = () => {
setSearchPopup, setSearchPopup,
toggleSearchElementSelection, toggleSearchElementSelection,
} = useMapStore(); } = useMapStore();
const { missionFormValues, setMissionFormValues, setOpen, isOpen, editingMissionId } = const { missionFormValues, setMissionFormValues, setOpen, isOpen } = usePannelStore(
usePannelStore((state) => state); (state) => state,
);
const [showRulerOptions, setShowRulerOptions] = useState(false); const [showRulerOptions, setShowRulerOptions] = useState(false);
const [rulerHover, setRulerHover] = useState(false); const [rulerHover, setRulerHover] = useState(false);
const [rulerOptionsHover, setRulerOptionsHover] = useState(false); const [rulerOptionsHover, setRulerOptionsHover] = useState(false);

View File

@@ -72,7 +72,7 @@ const MissionPopupContent = ({
default: default:
return <span className="text-gray-100">Error</span>; return <span className="text-gray-100">Error</span>;
} }
}, [currentTab, mission]); }, [currentTab, hpgNeedsAttention, mission]);
const setOpenMissionMarker = useMapStore((state) => state.setOpenMissionMarker); const setOpenMissionMarker = useMapStore((state) => state.setOpenMissionMarker);
const { anchor } = useSmartPopup(); const { anchor } = useSmartPopup();
@@ -350,6 +350,10 @@ const MissionMarker = ({ mission }: { mission: Mission }) => {
editingMissionId, editingMissionId,
mission.addressLat, mission.addressLat,
mission.addressLng, mission.addressLng,
mission.hpgLocationLat,
mission.hpgLocationLng,
mission.hpgValidationState,
mission.id,
missionFormValues?.addressLat, missionFormValues?.addressLat,
missionFormValues?.addressLng, missionFormValues?.addressLng,
]); ]);

View File

@@ -8,7 +8,7 @@ import { useEffect } from "react";
export const SearchElements = () => { export const SearchElements = () => {
const { searchElements, openMissionMarker, setSearchElements } = useMapStore(); const { searchElements, openMissionMarker, setSearchElements } = useMapStore();
const { isOpen: pannelOpen, editingMissionId } = usePannelStore((state) => state); const { isOpen: pannelOpen } = usePannelStore((state) => state);
const { data: missions } = useQuery({ const { data: missions } = useQuery({
queryKey: ["missions"], queryKey: ["missions"],
queryFn: () => queryFn: () =>
@@ -42,7 +42,7 @@ export const SearchElements = () => {
); );
setSearchElements(elements.filter((e) => !!e)); setSearchElements(elements.filter((e) => !!e));
} }
}, [openMissionMarker, pannelOpen, missions]); }, [openMissionMarker, pannelOpen, missions, setSearchElements]);
const SearchElement = ({ element }: { element: OSMWay }) => { const SearchElement = ({ element }: { element: OSMWay }) => {
const { toggleSearchElementSelection } = useMapStore(); const { toggleSearchElementSelection } = useMapStore();

View File

@@ -250,7 +250,7 @@ const StationTab = ({ aircraft }: { aircraft: ConnectedAircraft & { Station: Sta
const lstName = useMemo(() => { const lstName = useMemo(() => {
if (!aircraft.posLng || !aircraft.posLat) return station.bosRadioArea; if (!aircraft.posLng || !aircraft.posLat) return station.bosRadioArea;
return findLeitstelleForPosition(aircraft.posLng, aircraft.posLat); return findLeitstelleForPosition(aircraft.posLng, aircraft.posLat);
}, [aircraft.posLng, aircraft.posLat]); }, [aircraft.posLng, aircraft.posLat, station.bosRadioArea]);
return ( return (
<div className="p-4 text-base-content"> <div className="p-4 text-base-content">

View File

@@ -18,7 +18,6 @@ import {
SmartphoneNfc, SmartphoneNfc,
CheckCheck, CheckCheck,
Cross, Cross,
Radio,
Route, Route,
} from "lucide-react"; } from "lucide-react";
import { import {
@@ -26,12 +25,9 @@ import {
HpgState, HpgState,
HpgValidationState, HpgValidationState,
Mission, Mission,
MissionAlertLog,
MissionCompletedLog,
MissionLog, MissionLog,
MissionMessageLog, MissionMessageLog,
Prisma, Prisma,
Station,
} from "@repo/db"; } from "@repo/db";
import { usePannelStore } from "_store/pannelStore"; import { usePannelStore } from "_store/pannelStore";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
@@ -143,13 +139,16 @@ const Einsatzdetails = ({
state: "finished", state: "finished",
missionLog: { missionLog: {
push: { push: {
type: "completed-log", toJSON: () => ({
auto: false, type: "message-log",
timeStamp: new Date().toISOString(), auto: false,
data: { timeStamp: new Date().toISOString(),
user: getPublicUser(session.data?.user, { ignorePrivacy: true }), data: {
}, message: "Einsatz abgeschlossen",
} as any, user: getPublicUser(session.data.user, { ignorePrivacy: true }),
},
}),
},
}, },
}, },
}); });
@@ -408,11 +407,6 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
refetchMissionStationIds(); refetchMissionStationIds();
}, [mission.missionStationIds, refetchMissionStationIds]); }, [mission.missionStationIds, refetchMissionStationIds]);
const { data: allStations } = useQuery({
queryKey: ["stations"],
queryFn: () => getStationsAPI(),
});
const sendAlertMutation = useMutation({ const sendAlertMutation = useMutation({
mutationKey: ["missions"], mutationKey: ["missions"],
mutationFn: ({ mutationFn: ({
@@ -527,6 +521,7 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
menuPlacement="top" menuPlacement="top"
className="min-w-[320px] flex-1" className="min-w-[320px] flex-1"
isMulti={false} isMulti={false}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onChange={(v: any) => { onChange={(v: any) => {
setSelectedStation(v); setSelectedStation(v);
}} }}

View File

@@ -1,13 +1,12 @@
"use client"; "use client";
import { PublicUser } from "@repo/db"; import { PublicUser } from "@repo/db";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { cn, PenaltyDropdown } from "@repo/shared-components"; import { PenaltyDropdown } from "@repo/shared-components";
import { getConnectedAircraftsAPI, kickAircraftAPI } from "_querys/aircrafts"; import { getConnectedAircraftsAPI, kickAircraftAPI } from "_querys/aircrafts";
import { getConnectedDispatcherAPI, kickDispatcherAPI } from "_querys/dispatcher"; import { getConnectedDispatcherAPI, kickDispatcherAPI } from "_querys/dispatcher";
import { getLivekitRooms, kickLivekitParticipant } from "_querys/livekit"; import { getLivekitRooms, kickLivekitParticipant } from "_querys/livekit";
import { ParticipantInfo } from "livekit-server-sdk"; import { ParticipantInfo } from "livekit-server-sdk";
import { import {
Eye,
LockKeyhole, LockKeyhole,
Plane, Plane,
RedoDot, RedoDot,
@@ -17,7 +16,7 @@ import {
UserCheck, UserCheck,
Workflow, Workflow,
} from "lucide-react"; } from "lucide-react";
import { ReactNode, useRef, useState } from "react"; import { useRef } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
export default function AdminPanel() { export default function AdminPanel() {

View File

@@ -5,7 +5,6 @@ import { SettingsIcon, Volume2 } from "lucide-react";
import MicVolumeBar from "_components/MicVolumeIndication"; import MicVolumeBar from "_components/MicVolumeIndication";
import { useMutation, useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { editUserAPI, getUserAPI } from "_querys/user"; import { editUserAPI, getUserAPI } from "_querys/user";
import { Prisma } from "@repo/db";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { useAudioStore } from "_store/audioStore"; import { useAudioStore } from "_store/audioStore";
import toast from "react-hot-toast"; import toast from "react-hot-toast";

View File

@@ -36,6 +36,7 @@ export function findClosestPolygon(
const polygon = toPolygonFeature(way.nodes); const polygon = toPolygonFeature(way.nodes);
if (!polygon) continue; if (!polygon) continue;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const center = centroid(polygon as any).geometry.coordinates; // [lon, lat] const center = centroid(polygon as any).geometry.coordinates; // [lon, lat]
const newDistance = distance([referencePoint.lon, referencePoint.lat], center); const newDistance = distance([referencePoint.lon, referencePoint.lat], center);

View File

@@ -1,10 +1,10 @@
import { point, multiPolygon, booleanPointInPolygon, booleanIntersects, polygon } from "@turf/turf"; import { point, booleanPointInPolygon, polygon } from "@turf/turf";
import leitstellenGeoJSON from "../_components/map/_geojson/Leitstellen.json"; // Pfad anpassen import leitstellenGeoJSON from "../_components/map/_geojson/Leitstellen.json"; // Pfad anpassen
export function findLeitstelleForPosition(lat: number, lng: number) { export function findLeitstelleForPosition(lat: number, lng: number) {
const heliPoint = point([lat, lng]); const heliPoint = point([lat, lng]);
for (const feature of (leitstellenGeoJSON as any).features) { for (const feature of (leitstellenGeoJSON as GeoJSON.FeatureCollection).features) {
const geom = feature.geometry; const geom = feature.geometry;
if (geom.type === "Polygon") { if (geom.type === "Polygon") {

View File

@@ -1,8 +1,6 @@
import { useAudioStore } from "_store/audioStore"; import { useAudioStore } from "_store/audioStore";
import { import {
LocalParticipant,
LocalTrackPublication, LocalTrackPublication,
Participant,
RemoteParticipant, RemoteParticipant,
RemoteTrack, RemoteTrack,
RemoteTrackPublication, RemoteTrackPublication,
@@ -30,19 +28,12 @@ export const handleTrackSubscribed = (
} }
}; };
export const handleTrackUnsubscribed = ( export const handleTrackUnsubscribed = (track: RemoteTrack) => {
track: RemoteTrack,
publication: RemoteTrackPublication,
participant: RemoteParticipant,
) => {
// remove tracks from all attached elements // remove tracks from all attached elements
track.detach(); track.detach();
}; };
export const handleLocalTrackUnpublished = ( export const handleLocalTrackUnpublished = (publication: LocalTrackPublication) => {
publication: LocalTrackPublication,
participant: LocalParticipant,
) => {
// when local tracks are ended, update UI to remove them from rendering // when local tracks are ended, update UI to remove them from rendering
publication.track?.detach(); publication.track?.detach();
}; };

View File

@@ -1,4 +1,4 @@
import { ConnectedAircraft, PositionLog, Prisma, PublicUser, Station } from "@repo/db"; import { ConnectedAircraft, PositionLog, Prisma, Station } from "@repo/db";
import axios from "axios"; import axios from "axios";
import { serverApi } from "_helpers/axios"; import { serverApi } from "_helpers/axios";
import { checkSimulatorConnected } from "@repo/shared-components"; import { checkSimulatorConnected } from "@repo/shared-components";

View File

@@ -1,4 +1,4 @@
import { ConnectedAircraft, ConnectedDispatcher, Prisma } from "@repo/db"; import { ConnectedDispatcher, Prisma } from "@repo/db";
import { serverApi } from "_helpers/axios"; import { serverApi } from "_helpers/axios";
import axios from "axios"; import axios from "axios";

View File

@@ -2,12 +2,12 @@ import { Mission, MissionSdsLog, Prisma } from "@repo/db";
import axios from "axios"; import axios from "axios";
import { serverApi } from "_helpers/axios"; import { serverApi } from "_helpers/axios";
export const getMissionsAPI = async ( export const getMissionsAPI = async <T = Mission>(
filter?: Prisma.MissionWhereInput, filter?: Prisma.MissionWhereInput,
include?: Prisma.MissionInclude, include?: Prisma.MissionInclude,
orderBy?: Prisma.MissionOrderByWithRelationInput, orderBy?: Prisma.MissionOrderByWithRelationInput,
) => { ): Promise<T[]> => {
const res = await axios.get<Mission[]>("/api/missions", { const res = await axios.get<T[]>("/api/missions", {
params: { params: {
filter: JSON.stringify(filter), filter: JSON.stringify(filter),
include: JSON.stringify(include), include: JSON.stringify(include),

View File

@@ -1,5 +1,3 @@
import { raw } from "../../../../packages/database/generated/client/runtime/library";
export const getOsmAddress = async (lat: number, lng: number) => { export const getOsmAddress = async (lat: number, lng: number) => {
const address = await fetch( const address = await fetch(
`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json`, `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json`,

View File

@@ -65,7 +65,7 @@ export const useAudioStore = create<TalkState>((set, get) => ({
const newSpeaktingParticipants = get().speakingParticipants.filter( const newSpeaktingParticipants = get().speakingParticipants.filter(
(p) => !(p.identity === participant.identity), (p) => !(p.identity === participant.identity),
); );
set((state) => ({ set(() => ({
speakingParticipants: newSpeaktingParticipants, speakingParticipants: newSpeaktingParticipants,
})); }));
if (newSpeaktingParticipants.length === 0 && get().transmitBlocked) { if (newSpeaktingParticipants.length === 0 && get().transmitBlocked) {
@@ -77,8 +77,7 @@ export const useAudioStore = create<TalkState>((set, get) => ({
set({ micDeviceId, micVolume }); set({ micDeviceId, micVolume });
}, },
toggleTalking: () => { toggleTalking: () => {
const { room, isTalking, micDeviceId, micVolume, speakingParticipants, transmitBlocked } = const { room, isTalking, micDeviceId, speakingParticipants, transmitBlocked } = get();
get();
if (!room) return; if (!room) return;
if (speakingParticipants.length > 0 && !isTalking && !transmitBlocked) { if (speakingParticipants.length > 0 && !isTalking && !transmitBlocked) {
@@ -187,7 +186,7 @@ interface PTTData {
} }
const handlePTT = (data: PTTData) => { const handlePTT = (data: PTTData) => {
const { shouldTransmit, source } = data; const { shouldTransmit } = data;
const { room, speakingParticipants } = useAudioStore.getState(); const { room, speakingParticipants } = useAudioStore.getState();
if (!room) return; if (!room) return;

View File

@@ -1,4 +1,4 @@
import { prisma, Prisma } from "@repo/db"; import { prisma } from "@repo/db";
import { NextRequest, NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest): Promise<NextResponse> { export async function GET(request: NextRequest): Promise<NextResponse> {

View File

@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { AuthOptions, getServerSession as getNextAuthServerSession } from "next-auth"; import { AuthOptions, getServerSession as getNextAuthServerSession } from "next-auth";
import { PrismaAdapter } from "@next-auth/prisma-adapter"; import { PrismaAdapter } from "@next-auth/prisma-adapter";
import Credentials from "next-auth/providers/credentials"; import Credentials from "next-auth/providers/credentials";
import { prisma, PrismaClient } from "@repo/db"; import { prisma } from "@repo/db";
export const options: AuthOptions = { export const options: AuthOptions = {
providers: [ providers: [
@@ -9,7 +10,7 @@ export const options: AuthOptions = {
credentials: { credentials: {
code: { label: "code", type: "code" }, code: { label: "code", type: "code" },
}, },
async authorize(credentials, req) { async authorize(credentials) {
try { try {
if (!credentials) throw new Error("No credentials provided"); if (!credentials) throw new Error("No credentials provided");
const code = await prisma.oAuthToken.findFirstOrThrow({ const code = await prisma.oAuthToken.findFirstOrThrow({
@@ -60,7 +61,7 @@ export const options: AuthOptions = {
adapter: PrismaAdapter(prisma as any), adapter: PrismaAdapter(prisma as any),
callbacks: { callbacks: {
jwt: async ({ token, user, ...rest }) => { jwt: async ({ token, user }) => {
if (user && "firstname" in user) { if (user && "firstname" in user) {
return { return {
...token, ...token,
@@ -69,7 +70,7 @@ export const options: AuthOptions = {
} }
return token; return token;
}, },
session: async ({ session, user, token }) => { session: async ({ session, token }) => {
const dbUser = await prisma.user.findUnique({ const dbUser = await prisma.user.findUnique({
where: { where: {
id: token?.sub, id: token?.sub,

View File

@@ -3,15 +3,10 @@ import { RoomManager } from "_helpers/LivekitRoomManager";
import { getServerSession } from "api/auth/[...nextauth]/auth"; import { getServerSession } from "api/auth/[...nextauth]/auth";
import { NextRequest } from "next/server"; import { NextRequest } from "next/server";
export const GET = async (request: NextRequest) => { export const GET = async () => {
const session = await getServerSession(); const session = await getServerSession();
if (!session) return Response.json({ message: "Unauthorized" }, { status: 401 }); if (!session) return Response.json({ message: "Unauthorized" }, { status: 401 });
const user = await prisma.user.findUnique({
where: {
id: session.user.id,
},
});
const rooms = await RoomManager.listRooms(); const rooms = await RoomManager.listRooms();

View File

@@ -1,5 +1,4 @@
import { getServerSession } from "api/auth/[...nextauth]/auth"; import { getServerSession } from "api/auth/[...nextauth]/auth";
import { ROOMS } from "_data/livekitRooms";
import { AccessToken } from "livekit-server-sdk"; import { AccessToken } from "livekit-server-sdk";
import { NextRequest } from "next/server"; import { NextRequest } from "next/server";
import { getPublicUser, prisma } from "@repo/db"; import { getPublicUser, prisma } from "@repo/db";

View File

@@ -1,4 +1,4 @@
import { PositionLog, Prisma, prisma, User } from "@repo/db"; import { PositionLog, prisma, User } from "@repo/db";
import { getServerSession } from "api/auth/[...nextauth]/auth"; import { getServerSession } from "api/auth/[...nextauth]/auth";
import { verify } from "jsonwebtoken"; import { verify } from "jsonwebtoken";

View File

@@ -1,4 +1,4 @@
import { nextJsConfig } from "@repo/eslint-config/next-js"; import nextJsConfig from "@repo/eslint-config/next-js";
/** @type {import("eslint").Linter.Config} */ /** @type {import("eslint").Linter.Config} */
export default nextJsConfig; export default nextJsConfig;

View File

@@ -12,6 +12,7 @@
"check-types": "tsc --noEmit" "check-types": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^3.3.1",
"@hookform/resolvers": "^5.1.1", "@hookform/resolvers": "^5.1.1",
"@livekit/components-react": "^2.9.12", "@livekit/components-react": "^2.9.12",
"@livekit/components-styles": "^1.1.6", "@livekit/components-styles": "^1.1.6",
@@ -34,6 +35,7 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"daisyui": "^5.0.43", "daisyui": "^5.0.43",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"eslint-config-next": "^15.3.4",
"geojson": "^0.5.0", "geojson": "^0.5.0",
"i": "^0.3.7", "i": "^0.3.7",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",

View File

@@ -1,4 +1,3 @@
import NextAuth from "next-auth";
import { User as IUser } from "@repo/db"; import { User as IUser } from "@repo/db";
declare module "next-auth" { declare module "next-auth" {

View File

@@ -6,8 +6,8 @@ export const addMessage = async (notam: Prisma.ConfigCreateInput) => {
await prisma.config.create({ await prisma.config.create({
data: notam, data: notam,
}); });
} catch (error) { } catch (e) {
throw new Error("Failed to add message"); throw new Error(`Failed to add message: ${e instanceof Error ? e.message : "Unknown error"}`);
} }
}; };
@@ -16,7 +16,7 @@ export const disableMessage = async () => {
await prisma.config.create({ await prisma.config.create({
data: {}, data: {},
}); });
} catch (error) { } catch (e) {
throw new Error("Failed to disable message"); throw new Error(`Failed to add message: ${e instanceof Error ? e.message : "Unknown error"}`);
} }
}; };

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { Check, MessageSquareWarning, Settings } from "lucide-react"; import { Check, Settings } from "lucide-react";
import { MessageForm } from "./_components/MessageForm"; import { MessageForm } from "./_components/MessageForm";
import { PaginatedTable, PaginatedTableRef } from "_components/PaginatedTable"; import { PaginatedTable, PaginatedTableRef } from "_components/PaginatedTable";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";

View File

@@ -1,5 +1,5 @@
import { Event, Participant } from "@repo/db"; import { Event, Participant } from "@repo/db";
import { EventAppointmentOptionalDefaults } from "@repo/db/zod"; import { EventAppointmentOptionalDefaults, InputJsonValueType } from "@repo/db/zod";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { RefObject, useRef } from "react"; import { RefObject, useRef } from "react";
@@ -45,7 +45,7 @@ export const AppointmentModal = ({
</button> </button>
</form> </form>
<h3 className="font-bold text-lg">Termin {appointmentForm.watch("id")}</h3>
<form <form
onSubmit={appointmentForm.handleSubmit(async (values) => { onSubmit={appointmentForm.handleSubmit(async (values) => {
if (!event) return; if (!event) return;
@@ -55,13 +55,13 @@ export const AppointmentModal = ({
})} })}
className="flex flex-col" className="flex flex-col"
> >
<DateInput <div className="flex justify-between mr-7">
control={appointmentForm.control} <h3 className="font-bold text-lg">Termin {appointmentForm.watch("id")}</h3>
name="appointmentDate" <DateInput
showTimeInput value={new Date(appointmentForm.watch("appointmentDate") || Date.now())}
timeCaption="Uhrzeit" onChange={(date) => appointmentForm.setValue("appointmentDate", date)}
showTimeCaption />
/> </div>
<div> <div>
<PaginatedTable <PaginatedTable
hide={appointmentForm.watch("id") === undefined} hide={appointmentForm.watch("id") === undefined}
@@ -150,7 +150,7 @@ export const AppointmentModal = ({
attended: false, attended: false,
appointmentCancelled: true, appointmentCancelled: true,
statusLog: [ statusLog: [
...(row.original.statusLog as any), ...(row.original.statusLog as InputJsonValueType[]),
{ {
event: "Gefehlt an Event", event: "Gefehlt an Event",
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
@@ -169,7 +169,7 @@ export const AppointmentModal = ({
); );
}, },
}, },
] as ColumnDef<Participant, any>[] ] as ColumnDef<Participant>[]
} }
prismaModel={"participant"} prismaModel={"participant"}
filter={{ filter={{

View File

@@ -59,9 +59,7 @@ export const ParticipantModal = ({ participantForm, ref }: ParticipantModalProps
if (!participantForm.watch("id")) return; if (!participantForm.watch("id")) return;
const participant = participantForm.getValues(); const participant = participantForm.getValues();
await handleParticipantFinished(participant.id.toString()).catch((e) => { await handleParticipantFinished(participant.id.toString()).catch(() => {});
const error = e as AxiosError;
});
toast.success("Workflow erfolgreich ausgeführt"); toast.success("Workflow erfolgreich ausgeführt");
router.refresh(); router.refresh();
@@ -119,10 +117,10 @@ export const ParticipantModal = ({ participantForm, ref }: ParticipantModalProps
<div className="flex flex-col"> <div className="flex flex-col">
<h3 className="text-xl">Verlauf</h3> <h3 className="text-xl">Verlauf</h3>
{(participantForm.watch("statusLog") as unknown as ParticipantLog[])?.map((s) => ( {(participantForm.watch("statusLog") as unknown as ParticipantLog[])?.map((s) => (
<div className="flex justify-between" key={(s as any).timestamp}> <div className="flex justify-between" key={s.timestamp.toString()}>
<p>{s.event}</p> <p>{s.event}</p>
<p>{s.user}</p> <p>{s.user}</p>
<p>{new Date((s as any).timestamp).toLocaleString()}</p> <p>{new Date(s.timestamp).toLocaleString()}</p>
</div> </div>
))} ))}
</div> </div>

View File

@@ -1,11 +1,8 @@
"use server"; "use server";
import { prisma, Prisma, Event, Participant, EventAppointment } from "@repo/db"; import { prisma, Prisma, Event, Participant } from "@repo/db";
export const upsertEvent = async ( export const upsertEvent = async (event: Prisma.EventCreateInput, id?: Event["id"]) => {
event: Prisma.EventCreateInput,
id?: Event["id"],
) => {
const newEvent = id const newEvent = id
? await prisma.event.update({ ? await prisma.event.update({
where: { id: id }, where: { id: id },

View File

@@ -1,4 +1,3 @@
import { prisma } from "@repo/db";
import { Form } from "../_components/Form"; import { Form } from "../_components/Form";
export default async () => { export default async () => {

View File

@@ -1,23 +1,36 @@
import { PartyPopperIcon } from "lucide-react"; import { PartyPopperIcon } from "lucide-react";
import { PaginatedTable } from "../../../_components/PaginatedTable"; import { PaginatedTable } from "../../../_components/PaginatedTable";
import Link from "next/link"; import Link from "next/link";
import { ColumnDef } from "@tanstack/react-table";
import { Event } from "@repo/db";
export default function Page() { export default function Page() {
return ( return (
<> <>
<PaginatedTable <PaginatedTable
showEditButton
prismaModel="event" prismaModel="event"
columns={[ columns={
{ [
header: "Name", {
accessorKey: "name", header: "Name",
}, accessorKey: "name",
{ },
header: "Versteckt", {
accessorKey: "hidden", header: "Versteckt",
}, accessorKey: "hidden",
]} },
{
header: "Aktionen",
cell: ({ row }) => (
<div className="flex items-center gap-1">
<Link href={`/admin/event/${row.original.id}`}>
<button className="btn btn-sm">Edit</button>
</Link>
</div>
),
},
] as ColumnDef<Event>[]
}
leftOfSearch={ leftOfSearch={
<span className="flex items-center gap-2"> <span className="flex items-center gap-2">
<PartyPopperIcon className="w-5 h-5" /> Events <PartyPopperIcon className="w-5 h-5" /> Events

View File

@@ -2,7 +2,6 @@
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { KeywordOptionalDefaultsSchema } from "@repo/db/zod"; import { KeywordOptionalDefaultsSchema } from "@repo/db/zod";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod";
import { KEYWORD_CATEGORY, Keyword } from "@repo/db"; import { KEYWORD_CATEGORY, Keyword } from "@repo/db";
import { FileText } from "lucide-react"; import { FileText } from "lucide-react";
import { Input } from "../../../../_components/ui/Input"; import { Input } from "../../../../_components/ui/Input";
@@ -24,7 +23,7 @@ export const KeywordForm = ({ keyword }: { keyword?: Keyword }) => {
<form <form
onSubmit={form.handleSubmit(async (values) => { onSubmit={form.handleSubmit(async (values) => {
setLoading(true); setLoading(true);
const createdKeyword = await upsertKeyword(values, keyword?.id); await upsertKeyword(values, keyword?.id);
setLoading(false); setLoading(false);
if (!keyword) redirect(`/admin/keyword`); if (!keyword) redirect(`/admin/keyword`);
})} })}

View File

@@ -9,7 +9,6 @@ export default () => {
<> <>
<PaginatedTable <PaginatedTable
initialOrderBy={[{ id: "category", desc: true }]} initialOrderBy={[{ id: "category", desc: true }]}
showEditButton
prismaModel="keyword" prismaModel="keyword"
searchFields={["name", "abreviation", "description"]} searchFields={["name", "abreviation", "description"]}
columns={ columns={
@@ -26,6 +25,16 @@ export default () => {
header: "Name", header: "Name",
accessorKey: "name", accessorKey: "name",
}, },
{
header: "Aktionen",
cell: ({ row }) => (
<div className="flex items-center gap-1">
<Link href={`/admin/keyword/${row.original.id}`}>
<button className="btn btn-sm">bearbeiten</button>
</Link>
</div>
),
},
] as ColumnDef<Keyword>[] ] as ColumnDef<Keyword>[]
} }
leftOfSearch={ leftOfSearch={

View File

@@ -1,8 +1,7 @@
"use client"; "use client";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { StationOptionalDefaultsSchema } from "@repo/db/zod"; import { StationOptionalDefaultsSchema } from "@repo/db/zod";
import { set, useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod";
import { BosUse, Country, Station } from "@repo/db"; import { BosUse, Country, Station } from "@repo/db";
import { FileText, LocateIcon, PlaneIcon } from "lucide-react"; import { FileText, LocateIcon, PlaneIcon } from "lucide-react";
import { Input } from "../../../../_components/ui/Input"; import { Input } from "../../../../_components/ui/Input";

View File

@@ -1,32 +1,46 @@
"use client";
import { DatabaseBackupIcon } from "lucide-react"; import { DatabaseBackupIcon } from "lucide-react";
import { PaginatedTable } from "../../../_components/PaginatedTable"; import { PaginatedTable } from "../../../_components/PaginatedTable";
import Link from "next/link"; import Link from "next/link";
import { ColumnDef } from "@tanstack/react-table";
import { Station } from "@repo/db";
const page = () => { const page = () => {
return ( return (
<> <>
<PaginatedTable <PaginatedTable
showEditButton
prismaModel="station" prismaModel="station"
searchFields={["bosCallsign", "bosUse", "country", "operator"]} searchFields={["bosCallsign", "bosUse", "country", "operator"]}
columns={[ columns={
{ [
header: "BOS Name", {
accessorKey: "bosCallsign", header: "BOS Name",
}, accessorKey: "bosCallsign",
{ },
header: "Bos Use", {
accessorKey: "bosUse", header: "Bos Use",
}, accessorKey: "bosUse",
{ },
header: "Country", {
accessorKey: "country", header: "Country",
}, accessorKey: "country",
{ },
header: "operator", {
accessorKey: "operator", header: "operator",
}, accessorKey: "operator",
]} },
{
header: "Aktionen",
cell: ({ row }) => (
<div className="flex items-center gap-1">
<Link href={`/admin/event/${row.original.id}`}>
<button className="btn btn-sm">Edit</button>
</Link>
</div>
),
},
] as ColumnDef<Station>[]
}
leftOfSearch={ leftOfSearch={
<span className="flex items-center gap-2"> <span className="flex items-center gap-2">
<DatabaseBackupIcon className="w-5 h-5" /> Stationen <DatabaseBackupIcon className="w-5 h-5" /> Stationen
@@ -35,9 +49,7 @@ const page = () => {
rightOfSearch={ rightOfSearch={
<p className="text-2xl font-semibold text-left flex items-center gap-2 justify-between"> <p className="text-2xl font-semibold text-left flex items-center gap-2 justify-between">
<Link href={"/admin/station/new"}> <Link href={"/admin/station/new"}>
<button className="btn btn-sm btn-outline btn-primary"> <button className="btn btn-sm btn-outline btn-primary">Erstellen</button>
Erstellen
</button>
</Link> </Link>
</p> </p>
} }

View File

@@ -39,26 +39,23 @@ import { PaginatedTable, PaginatedTableRef } from "_components/PaginatedTable";
import { cn } from "@repo/shared-components"; import { cn } from "@repo/shared-components";
import { import {
ChartBarBigIcon, ChartBarBigIcon,
Check,
Eye, Eye,
LockKeyhole, LockKeyhole,
PlaneIcon, PlaneIcon,
RedoDot,
ShieldUser, ShieldUser,
Timer, Timer,
Trash2, Trash2,
Users, Users,
X,
} from "lucide-react"; } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";
import { Error } from "_components/Error"; import { Error } from "_components/Error";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { setStandardName } from "../../../../../../helper/discord"; import { setStandardName } from "(app)/../../helper/discord";
import { penaltyColumns } from "(app)/admin/penalty/columns"; import { penaltyColumns } from "(app)/admin/penalty/columns";
import { addPenalty, editPenaltys } from "(app)/admin/penalty/actions"; import { addPenalty, editPenaltys } from "(app)/admin/penalty/actions";
import { reportColumns } from "(app)/admin/report/columns"; import { reportColumns } from "(app)/admin/report/columns";
import { sendMail, sendMailByTemplate } from "../../../../../../helper/mail"; import { sendMailByTemplate } from "(app)/../../helper/mail";
interface ProfileFormProps { interface ProfileFormProps {
user: User; user: User;

View File

@@ -1,13 +1,16 @@
"use client";
import { User2 } from "lucide-react"; import { User2 } from "lucide-react";
import { PaginatedTable } from "../../../_components/PaginatedTable"; import { PaginatedTable } from "../../../_components/PaginatedTable";
import { getServerSession } from "api/auth/[...nextauth]/auth"; import Link from "next/link";
import { ColumnDef } from "@tanstack/react-table";
import { User } from "@repo/db";
import { useSession } from "next-auth/react";
const AdminUserPage = async () => { const AdminUserPage = () => {
const session = await getServerSession(); const { data: session } = useSession();
return ( return (
<> <>
<PaginatedTable <PaginatedTable
showEditButton
prismaModel="user" prismaModel="user"
searchFields={["publicId", "firstname", "lastname", "email"]} searchFields={["publicId", "firstname", "lastname", "email"]}
initialOrderBy={[ initialOrderBy={[
@@ -16,28 +19,40 @@ const AdminUserPage = async () => {
desc: false, desc: false,
}, },
]} ]}
columns={[ columns={
{ [
header: "ID", {
accessorKey: "publicId", header: "ID",
}, accessorKey: "publicId",
{ },
header: "Vorname", {
accessorKey: "firstname", header: "Vorname",
}, accessorKey: "firstname",
{ },
header: "Nachname", {
accessorKey: "lastname", header: "Nachname",
}, accessorKey: "lastname",
...(session?.user.permissions.includes("ADMIN_USER_ADVANCED") },
? [ ...(session?.user.permissions.includes("ADMIN_USER_ADVANCED")
{ ? [
header: "Email", {
accessorKey: "email", header: "Email",
}, accessorKey: "email",
] },
: []), ]
]} : []),
{
header: "Aktionen",
cell: ({ row }) => (
<div className="flex items-center gap-1">
<Link href={`/admin/event/${row.original.id}`}>
<button className="btn btn-sm">Anzeigen</button>
</Link>
</div>
),
},
] as ColumnDef<User>[]
} // Define the columns for the user table
leftOfSearch={ leftOfSearch={
<p className="text-2xl font-semibold text-left flex items-center gap-2"> <p className="text-2xl font-semibold text-left flex items-center gap-2">
<User2 className="w-5 h-5" /> Benutzer <User2 className="w-5 h-5" /> Benutzer

View File

@@ -17,7 +17,9 @@ export const EventCard = ({
Participants: Participant[]; Participants: Participant[];
}; };
selectedAppointments: EventAppointment[]; selectedAppointments: EventAppointment[];
appointments: EventAppointment[]; appointments: (EventAppointment & {
Participants: { userId: string }[];
})[];
}) => { }) => {
return ( return (
<div className="col-span-full"> <div className="col-span-full">

View File

@@ -16,7 +16,11 @@ import {
TriangleAlert, TriangleAlert,
} from "lucide-react"; } from "lucide-react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { ParticipantOptionalDefaults, ParticipantOptionalDefaultsSchema } from "@repo/db/zod"; import {
InputJsonValueType,
ParticipantOptionalDefaults,
ParticipantOptionalDefaultsSchema,
} from "@repo/db/zod";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { Select } from "../../../_components/ui/Select"; import { Select } from "../../../_components/ui/Select";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
@@ -24,11 +28,14 @@ import { handleParticipantEnrolled } from "../../../../helper/events";
import { eventCompleted } from "@repo/shared-components"; import { eventCompleted } from "@repo/shared-components";
import MDEditor from "@uiw/react-md-editor"; import MDEditor from "@uiw/react-md-editor";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { formatDate } from "date-fns";
interface ModalBtnProps { interface ModalBtnProps {
title: string; title: string;
event: Event; event: Event;
dates: EventAppointment[]; dates: (EventAppointment & {
Participants: { userId: string }[];
})[];
selectedAppointments: EventAppointment[]; selectedAppointments: EventAppointment[];
participant?: Participant; participant?: Participant;
user: User; user: User;
@@ -88,14 +95,16 @@ const ModalBtn = ({
(date) => (date) =>
date.id === selectAppointmentForm.watch("eventAppointmentId") || selectedAppointment?.id, date.id === selectAppointmentForm.watch("eventAppointmentId") || selectedAppointment?.id,
); );
const ownIndexInParticipantList = (selectedDate as any)?.Participants?.findIndex( const ownIndexInParticipantList = selectedDate?.Participants?.findIndex(
(p: Participant) => p.userId === user.id, (p) => p.userId === user.id,
); );
const ownPlaceInParticipantList = const ownPlaceInParticipantList =
ownIndexInParticipantList === -1 typeof ownIndexInParticipantList === "number"
? (selectedDate as any)?.Participants?.length + 1 ? ownIndexInParticipantList === -1
: ownIndexInParticipantList + 1; ? (selectedDate?.Participants?.length ?? 0) + 1
: ownIndexInParticipantList + 1
: undefined;
const missingRequirements = const missingRequirements =
event.requiredBadges?.length > 0 && event.requiredBadges?.length > 0 &&
@@ -167,13 +176,7 @@ const ModalBtn = ({
<Select <Select
form={selectAppointmentForm} form={selectAppointmentForm}
options={dates.map((date) => ({ options={dates.map((date) => ({
label: `${new Date(date.appointmentDate).toLocaleString("de-DE", { label: `${formatDate(date.appointmentDate, "dd.MM.yyyy HH:mm")} - (${date.Participants.length}/${event.maxParticipants})`,
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
})} - (${(date as any).Participants.length}/${event.maxParticipants})`,
value: date.id, value: date.id,
}))} }))}
name="eventAppointmentId" name="eventAppointmentId"
@@ -296,7 +299,7 @@ const ModalBtn = ({
userId: participant!.userId, userId: participant!.userId,
appointmentCancelled: true, appointmentCancelled: true,
statusLog: [ statusLog: [
...(participant?.statusLog as any), ...(participant?.statusLog as unknown as InputJsonValueType[]),
{ {
data: { data: {
appointmentId: selectedAppointment.id, appointmentId: selectedAppointment.id,

View File

@@ -1,4 +1,3 @@
import { Download } from "lucide-react";
import Image, { StaticImageData } from "next/image"; import Image, { StaticImageData } from "next/image";
import { ReactNode } from "react"; import { ReactNode } from "react";

View File

@@ -4,7 +4,6 @@ import { Service } from "../page";
import { generateToken } from "./action"; import { generateToken } from "./action";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { useErrorBoundary } from "react-error-boundary"; import { useErrorBoundary } from "react-error-boundary";
import { se } from "date-fns/locale";
import { PERMISSION } from "@repo/db"; import { PERMISSION } from "@repo/db";
export const Authorize = ({ service }: { service: Service }) => { export const Authorize = ({ service }: { service: Service }) => {

View File

@@ -11,10 +11,10 @@ export const CustomErrorBoundary = ({ children }: { children?: React.ReactNode }
let errorTest; let errorTest;
let errorCode = 500; let errorCode = 500;
if ("statusCode" in error) { if ("statusCode" in error) {
errorCode = (error as any).statusCode; errorCode = error.statusCode;
} }
if ("message" in error || error instanceof Error) { if ("message" in error || error instanceof Error) {
errorTest = (error as any).message; errorTest = error.message;
} else if (typeof error === "string") { } else if (typeof error === "string") {
errorTest = error; errorTest = error;
} else { } else {

View File

@@ -1,8 +1,9 @@
"use client"; "use client";
import { useEffect, useState, useCallback, Ref, useImperativeHandle } from "react"; import { useState, Ref, useImperativeHandle } from "react";
import SortableTable, { Pagination, SortableTableProps } from "./Table"; import SortableTable, { Pagination, SortableTableProps } from "./Table";
import { PrismaClient } from "@repo/db"; import { PrismaClient } from "@repo/db";
import { getData } from "./pagiantedTableActions"; import { getData } from "./pagiantedTableActions";
import { useDebounce } from "@repo/shared-components";
export interface PaginatedTableRef { export interface PaginatedTableRef {
refresh: () => void; refresh: () => void;
@@ -10,9 +11,8 @@ export interface PaginatedTableRef {
interface PaginatedTableProps<TData> extends Omit<SortableTableProps<TData>, "data"> { interface PaginatedTableProps<TData> extends Omit<SortableTableProps<TData>, "data"> {
prismaModel: keyof PrismaClient; prismaModel: keyof PrismaClient;
filter?: Record<string, any>; filter?: Record<string, unknown>;
rowsPerPage?: number; rowsPerPage?: number;
showEditButton?: boolean;
searchFields?: string[]; searchFields?: string[];
include?: Record<string, boolean>; include?: Record<string, boolean>;
strictQuery?: boolean; strictQuery?: boolean;
@@ -26,7 +26,6 @@ interface PaginatedTableProps<TData> extends Omit<SortableTableProps<TData>, "da
export function PaginatedTable<TData>({ export function PaginatedTable<TData>({
prismaModel, prismaModel,
rowsPerPage = 10, rowsPerPage = 10,
showEditButton = false,
searchFields = [], searchFields = [],
filter, filter,
include, include,
@@ -42,7 +41,6 @@ export function PaginatedTable<TData>({
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(searchTerm);
const [orderBy, setOrderBy] = useState<Record<string, "asc" | "desc">>( const [orderBy, setOrderBy] = useState<Record<string, "asc" | "desc">>(
restProps.initialOrderBy restProps.initialOrderBy
? restProps.initialOrderBy.reduce( ? restProps.initialOrderBy.reduce(
@@ -60,16 +58,19 @@ export function PaginatedTable<TData>({
prismaModel, prismaModel,
rowsPerPage, rowsPerPage,
page * rowsPerPage, page * rowsPerPage,
debouncedSearchTerm, searchTerm,
searchFields, searchFields,
filter, filter,
include, include,
orderBy, orderBy,
strictQuery strictQuery
? restProps.columns ? restProps.columns
.filter((col: any) => "accessorKey" in col) .filter(
.map((col: any) => col.accessorKey) (col): col is { accessorKey: string } =>
.reduce((acc: Record<string, any>, key: string) => { typeof (col as { accessorKey?: unknown }).accessorKey === "string",
)
.map((col) => col.accessorKey)
.reduce<Record<string, boolean>>((acc, key) => {
acc[key] = true; acc[key] = true;
return acc; return acc;
}, {}) }, {})
@@ -82,35 +83,20 @@ export function PaginatedTable<TData>({
}); });
}; };
useEffect(() => {
RefreshTableData();
}, [filter, orderBy]);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
refresh: () => { refresh: () => {
RefreshTableData(); RefreshTableData();
}, },
})); }));
const debounce = (func: Function, delay: number) => { useDebounce(
let timer: NodeJS.Timeout; () => {
return (...args: any[]) => { RefreshTableData();
clearTimeout(timer); },
timer = setTimeout(() => func(...args), delay); 500,
}; [searchTerm, page, rowsPerPage, orderBy, filter],
};
const handleSearchChange = useCallback(
debounce((value: string) => {
setDebouncedSearchTerm(value);
}, 500),
[],
); );
useEffect(() => {
RefreshTableData();
}, [page, debouncedSearchTerm]);
return ( return (
<div className="space-y-4 m-4"> <div className="space-y-4 m-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -122,7 +108,6 @@ export function PaginatedTable<TData>({
value={searchTerm} value={searchTerm}
onChange={(e) => { onChange={(e) => {
setSearchTerm(e.target.value); setSearchTerm(e.target.value);
handleSearchChange(e.target.value);
setPage(0); // Reset to first page on search setPage(0); // Reset to first page on search
}} }}
className="input input-bordered w-full max-w-xs justify-end" className="input input-bordered w-full max-w-xs justify-end"
@@ -134,7 +119,6 @@ export function PaginatedTable<TData>({
<SortableTable <SortableTable
data={data} data={data}
prismaModel={prismaModel} prismaModel={prismaModel}
showEditButton={showEditButton}
setOrderBy={setOrderBy} setOrderBy={setOrderBy}
{...restProps} {...restProps}
/> />

View File

@@ -3,7 +3,7 @@
import { toast } from "react-hot-toast"; import { toast } from "react-hot-toast";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactNode, useEffect, useState } from "react"; import { ReactNode, useState } from "react";
export function QueryProvider({ children }: { children: ReactNode }) { export function QueryProvider({ children }: { children: ReactNode }) {
const [queryClient] = useState( const [queryClient] = useState(

View File

@@ -9,13 +9,11 @@ import {
flexRender, flexRender,
} from "@tanstack/react-table"; } from "@tanstack/react-table";
import { ArrowLeft, ArrowRight, ChevronDown, ChevronUp } from "lucide-react"; // Icons for sorting import { ArrowLeft, ArrowRight, ChevronDown, ChevronUp } from "lucide-react"; // Icons for sorting
import Link from "next/link";
import { PrismaClient } from "@repo/db"; import { PrismaClient } from "@repo/db";
export interface SortableTableProps<TData> { export interface SortableTableProps<TData> {
data: TData[]; data: TData[];
columns: ColumnDef<TData>[]; columns: ColumnDef<TData>[];
showEditButton?: boolean;
prismaModel?: keyof PrismaClient; prismaModel?: keyof PrismaClient;
setOrderBy?: (orderBy: Record<string, "asc" | "desc">) => void; setOrderBy?: (orderBy: Record<string, "asc" | "desc">) => void;
initialOrderBy?: SortingState; initialOrderBy?: SortingState;
@@ -26,28 +24,13 @@ export default function SortableTable<TData>({
columns, columns,
initialOrderBy = [], initialOrderBy = [],
prismaModel, prismaModel,
showEditButton,
setOrderBy, setOrderBy,
}: SortableTableProps<TData>) { }: SortableTableProps<TData>) {
const [sorting, setSorting] = useState<SortingState>(initialOrderBy); const [sorting, setSorting] = useState<SortingState>(initialOrderBy);
const table = useReactTable({ const table = useReactTable({
data, data,
columns: showEditButton columns,
? [
...columns,
{
header: "Actions",
cell: ({ row }) => (
<div className="flex items-center gap-1">
<Link href={`/admin/${prismaModel as string}/${(row.original as any).id}`}>
<button className="btn btn-sm">Edit</button>
</Link>
</div>
),
},
]
: columns,
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(), getSortedRowModel: getSortedRowModel(),
onSortingChange: setSorting, onSortingChange: setSorting,

View File

@@ -15,7 +15,7 @@ export const Button = ({
return ( return (
<button <button
{...(props as any)} {...props}
className={cn("btn", props.className)} className={cn("btn", props.className)}
disabled={isLoadingState || props.disabled} disabled={isLoadingState || props.disabled}
onClick={async (e) => { onClick={async (e) => {
@@ -27,7 +27,7 @@ export const Button = ({
}} }}
> >
{isLoadingState && <span className="loading loading-spinner loading-sm"></span>} {isLoadingState && <span className="loading loading-spinner loading-sm"></span>}
{props.children as any} {props.children}
</button> </button>
); );
}; };

View File

@@ -1,32 +1,24 @@
import DatePicker, { DatePickerProps, registerLocale } from "react-datepicker"; import { formatDate } from "date-fns";
import { Control, Controller, FieldValues, Path } from "react-hook-form";
import { de } from "date-fns/locale";
registerLocale("de", de);
interface DateInputProps<T extends FieldValues> export const DateInput = ({
extends Omit<DatePickerProps, "onChange" | "selected"> { value,
control: Control<T>; onChange,
name: Path<T>;
}
export const DateInput = <T extends FieldValues>({
control,
name,
...props ...props
}: DateInputProps<T>) => { }: Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange"> & {
value?: Date | null;
onChange?: (date: Date) => void;
}) => {
return ( return (
<Controller <input
control={control} type="datetime-local"
name={name} className="input"
render={({ field }) => ( value={formatDate(value || new Date(), "yyyy-MM-dd hh:mm")}
<DatePicker onChange={(e) => {
className="input input-bordered mt-2" const date = e.target.value ? new Date(e.target.value) : null;
locale={"de"} if (!date) return;
onChange={(date) => field.onChange(date)} onChange?.(date);
selected={field.value} }}
{...(props as any)} {...props}
/>
)}
/> />
); );
}; };

View File

@@ -1,24 +1,18 @@
import { DetailedHTMLProps, InputHTMLAttributes, ReactNode } from 'react'; import { InputHTMLAttributes, ReactNode } from "react";
interface FormTextInputProps extends InputHTMLAttributes<HTMLInputElement> { interface FormTextInputProps extends InputHTMLAttributes<HTMLInputElement> {
error: any; error: ReactNode;
Svg: ReactNode; children?: ReactNode;
children?: ReactNode;
} }
export const FormTextInput = ({ export const FormTextInput = ({ error, children, ...props }: FormTextInputProps) => {
error, return (
Svg, <>
children, <label className="input input-bordered flex items-center gap-2">
...props {children}
}: FormTextInputProps) => { <input {...props} />
return ( </label>
<> <p className="text-error">{error}</p>
<label className="input input-bordered flex items-center gap-2"> </>
{children} );
<input {...props} />
</label>
<p className="text-error">{error}</p>
</>
);
}; };

View File

@@ -1,5 +1,6 @@
import DatePicker, { DatePickerProps, registerLocale } from "react-datepicker"; /* eslint-disable @typescript-eslint/no-explicit-any */
import { Control, Controller, FieldValues, Path, PathValue } from "react-hook-form"; import { DatePickerProps, registerLocale } from "react-datepicker";
import { Control, Controller, FieldValues, Path } from "react-hook-form";
import { de } from "date-fns/locale"; import { de } from "date-fns/locale";
import { useState } from "react"; import { useState } from "react";
import { cn } from "@repo/shared-components"; import { cn } from "@repo/shared-components";
@@ -44,7 +45,7 @@ export const ListInput = <T extends FieldValues>({
setValue(""); setValue("");
}} }}
type="button" type="button"
onSubmit={(e) => false} onSubmit={() => false}
> >
Hinzufügen Hinzufügen
</button> </button>

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client"; "use client";
import MDEditor from "@uiw/react-md-editor"; import MDEditor from "@uiw/react-md-editor";
import { FieldValues, Path, RegisterOptions, UseFormReturn } from "react-hook-form"; import { FieldValues, Path, RegisterOptions, UseFormReturn } from "react-hook-form";
@@ -5,7 +6,7 @@ import { cn } from "@repo/shared-components";
interface MarkdownEditorProps<T extends FieldValues> { interface MarkdownEditorProps<T extends FieldValues> {
name: Path<T>; name: Path<T>;
form: UseFormReturn<T>; form: UseFormReturn<any>;
formOptions?: RegisterOptions<T>; formOptions?: RegisterOptions<T>;
label?: string; label?: string;
placeholder?: string; placeholder?: string;

View File

@@ -1,19 +1,20 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client"; "use client";
import { FieldValues, Path, RegisterOptions, UseFormReturn } from "react-hook-form"; import { FieldValues, Path, RegisterOptions, UseFormReturn } from "react-hook-form";
import SelectTemplate, { Props as SelectTemplateProps, StylesConfig } from "react-select"; import SelectTemplate, { Props as SelectTemplateProps, StylesConfig } from "react-select";
import { cn } from "@repo/shared-components"; import { cn } from "@repo/shared-components";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import { CSSProperties } from "react";
interface SelectProps<T extends FieldValues> extends Omit<SelectTemplateProps, "form"> { interface SelectProps<T extends FieldValues> extends Omit<SelectTemplateProps, "form"> {
label?: any; label?: React.ReactNode;
name: Path<T>; name: Path<T>;
form: UseFormReturn<T> | any; form: UseFormReturn<any>;
formOptions?: RegisterOptions<T>; formOptions?: RegisterOptions<T>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} }
const customStyles: StylesConfig<any, false> = { type OptionType = { label: string; value: string };
const customStyles: StylesConfig<OptionType, false> = {
control: (provided) => ({ control: (provided) => ({
...provided, ...provided,
backgroundColor: "var(--color-base-100)", backgroundColor: "var(--color-base-100)",
@@ -55,7 +56,6 @@ const SelectCom = <T extends FieldValues>({
label = name, label = name,
placeholder = label, placeholder = label,
form, form,
formOptions,
className, className,
...inputProps ...inputProps
}: SelectProps<T>) => { }: SelectProps<T>) => {
@@ -74,7 +74,6 @@ const SelectCom = <T extends FieldValues>({
}); });
} }
form.trigger(name); form.trigger(name);
form.Dirty;
}} }}
value={ value={
(inputProps as any)?.isMulti (inputProps as any)?.isMulti

View File

@@ -1,10 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { FieldValues, Path, RegisterOptions, UseFormReturn } from "react-hook-form"; import { FieldValues, Path, RegisterOptions, UseFormReturn } from "react-hook-form";
import { cn } from "@repo/shared-components"; import { cn } from "@repo/shared-components";
interface InputProps<T extends FieldValues> interface InputProps<T extends FieldValues>
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "form"> { extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "form"> {
name: Path<T>; name: Path<T>;
form: UseFormReturn<T>; form: UseFormReturn<any>;
formOptions?: RegisterOptions<T>; formOptions?: RegisterOptions<T>;
label?: string; label?: string;
} }
@@ -13,7 +14,6 @@ export const Switch = <T extends FieldValues>({
name, name,
label = name, label = name,
form, form,
formOptions,
className, className,
...inputProps ...inputProps
}: InputProps<T>) => { }: InputProps<T>) => {
@@ -21,7 +21,12 @@ export const Switch = <T extends FieldValues>({
<div className="form-control "> <div className="form-control ">
<label className="label cursor-pointer w-full"> <label className="label cursor-pointer w-full">
<span className={cn("label-text text-left w-full", className)}>{label}</span> <span className={cn("label-text text-left w-full", className)}>{label}</span>
<input type="checkbox" className={cn("toggle", className)} {...form.register(name)} /> <input
type="checkbox"
className={cn("toggle", className)}
{...form.register(name)}
{...inputProps}
/>
</label> </label>
</div> </div>
); );

View File

@@ -1,7 +1,7 @@
import { AuthOptions, getServerSession as getNextAuthServerSession } from "next-auth"; import { AuthOptions, getServerSession as getNextAuthServerSession } from "next-auth";
import { PrismaAdapter } from "@next-auth/prisma-adapter"; import { PrismaAdapter } from "@next-auth/prisma-adapter";
import Credentials from "next-auth/providers/credentials"; import Credentials from "next-auth/providers/credentials";
import { DiscordAccount, prisma, User } from "@repo/db"; import { prisma } from "@repo/db";
import bcrypt from "bcryptjs"; import bcrypt from "bcryptjs";
import oldUser from "./var.User.json"; import oldUser from "./var.User.json";
import { createNewUserFromOld, OldUser } from "../../../../types/oldUser"; import { createNewUserFromOld, OldUser } from "../../../../types/oldUser";
@@ -70,7 +70,7 @@ export const options: AuthOptions = {
}, },
}, },
}, },
adapter: PrismaAdapter(prisma as any), adapter: PrismaAdapter(prisma),
callbacks: { callbacks: {
jwt: async ({ token, user }) => { jwt: async ({ token, user }) => {
if (user && "firstname" in user) { if (user && "firstname" in user) {
@@ -88,6 +88,7 @@ export const options: AuthOptions = {
}, },
}); });
if (!dbUser) { if (!dbUser) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return null as any; return null as any;
} }
return { return {

View File

@@ -1,7 +1,7 @@
import { prisma } from "@repo/db"; import { prisma } from "@repo/db";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET(request: Request): Promise<NextResponse> { export async function GET(): Promise<NextResponse> {
try { try {
const config = await prisma.config.findFirst({ const config = await prisma.config.findFirst({
orderBy: { orderBy: {

View File

@@ -7,7 +7,6 @@ import "./globals.css";
import { QueryProvider } from "_components/QueryClient"; import { QueryProvider } from "_components/QueryClient";
import { prisma } from "@repo/db"; import { prisma } from "@repo/db";
import React from "react"; import React from "react";
import { Error as ErrorComp } from "_components/Error";
import { Maintenance } from "@repo/shared-components"; import { Maintenance } from "@repo/shared-components";
const geistSans = Geist({ const geistSans = Geist({

View File

@@ -1,4 +1,4 @@
import { nextJsConfig } from "@repo/eslint-config/next-js"; import nextJsConfig from "@repo/eslint-config/next-js";
/** @type {import("eslint").Linter.Config} */ /** @type {import("eslint").Linter.Config} */
export default nextJsConfig; export default nextJsConfig;

View File

@@ -19,7 +19,7 @@ export const sendMailByTemplate = async (
| "email-verification" | "email-verification"
| "ban-notice" | "ban-notice"
| "timeban-notice", | "timeban-notice",
data: any, data: unknown,
) => { ) => {
try { try {
await fetch(`${process.env.NEXT_PUBLIC_HUB_SERVER_URL}/mail/template/${template}`, { await fetch(`${process.env.NEXT_PUBLIC_HUB_SERVER_URL}/mail/template/${template}`, {

View File

@@ -25,7 +25,7 @@ export const enrollUserInCourse = async (courseid: number | string, userid: numb
); );
return enrollmentResponse; return enrollmentResponse;
} catch (error) { } catch (error) {
return new Error("Failed to enroll user in course"); return error;
} }
}; };

View File

@@ -1,5 +1,5 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const removeImports = require("next-remove-imports")(); /* const removeImports = require("next-remove-imports")(); */
/* const nextConfig = removeImports({}); */ /* const nextConfig = removeImports({}); */
const nextConfig = {}; const nextConfig = {};

View File

@@ -31,7 +31,6 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"daisyui": "^5.0.43", "daisyui": "^5.0.43",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"eslint": "^9.30.0",
"eslint-config-next": "^15.3.4", "eslint-config-next": "^15.3.4",
"i": "^0.3.7", "i": "^0.3.7",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
@@ -52,8 +51,13 @@
"react-select": "^5.10.1", "react-select": "^5.10.1",
"tailwind-merge": "^3.3.1", "tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.11", "tailwindcss": "^4.1.11",
"typescript": "^5.8.3",
"zod": "^3.25.67", "zod": "^3.25.67",
"zustand": "^5.0.6" "zustand": "^5.0.6"
},
"devDependencies": {
"@eslint/js": "^9.30.0",
"eslint": "^9.30.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.33.1"
} }
} }

View File

@@ -1,4 +1,3 @@
import NextAuth from "next-auth";
import { User as IUser } from "@repo/db"; import { User as IUser } from "@repo/db";
declare module "next-auth" { declare module "next-auth" {

View File

@@ -1,14 +1,8 @@
import { Prisma } from "@prisma/client"; /* import { JsonArray, JsonObject } from "@prisma/client/runtime/library";
import { JsonArray, JsonObject } from "@prisma/client/runtime/library";
declare module "@prisma/client" { declare module "@prisma/client" {
export type InputJsonValue = export type InputJsonValue = string | number | boolean | null | JsonObject | JsonArray;
| string
| number
| boolean
| null
| JsonObject
| JsonArray;
export type JsonValue = any; // Erzwingt Flexibilität export type JsonValue = any; // Erzwingt Flexibilität
} }
*/

View File

@@ -24,5 +24,8 @@
"workspaces": [ "workspaces": [
"apps/*", "apps/*",
"packages/*" "packages/*"
] ],
"dependencies": {
"eslint": "^9.30.1"
}
} }

View File

@@ -1,49 +1,37 @@
import { defineConfig } from "eslint/config";
import js from "@eslint/js"; import js from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier"; import eslintConfigPrettier from "eslint-config-prettier";
import tseslint from "typescript-eslint"; import tseslint from "typescript-eslint";
import pluginReactHooks from "eslint-plugin-react-hooks"; import pluginReactHooks from "eslint-plugin-react-hooks";
import pluginReact from "eslint-plugin-react";
import globals from "globals"; import globals from "globals";
import pluginNext from "@next/eslint-plugin-next"; import pluginNext from "@next/eslint-plugin-next";
import { config as baseConfig } from "./base.js";
/** export default defineConfig([
* A custom ESLint configuration for libraries that use Next.js.
*
* @type {import("eslint").Linter.Config}
* */
export const nextJsConfig = [
...baseConfig,
js.configs.recommended,
eslintConfigPrettier,
...tseslint.configs.recommended,
{ {
...pluginReact.configs.flat.recommended, ignores: ["node_modules/*", "dist/*", ".next/*", "out/*"],
languageOptions: {
...pluginReact.configs.flat.recommended.languageOptions,
globals: {
...globals.serviceworker,
},
},
}, },
{ {
files: ["**/*.{js,ts,jsx,tsx}"],
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
},
plugins: { plugins: {
"react-hooks": pluginReactHooks,
"@next/next": pluginNext, "@next/next": pluginNext,
}, },
rules: {
...pluginNext.configs.recommended.rules,
...pluginNext.configs["core-web-vitals"].rules,
},
},
{
plugins: {
"react-hooks": pluginReactHooks,
},
settings: { react: { version: "detect" } },
rules: { rules: {
...pluginReactHooks.configs.recommended.rules, ...pluginReactHooks.configs.recommended.rules,
// React scope no longer necessary with new JSX transform. ...pluginNext.configs.recommended.rules,
"react/react-in-jsx-scope": "off", "react/react-in-jsx-scope": "off",
}, },
}, },
]; ...tseslint.config(js.configs.recommended, tseslint.configs.recommended, eslintConfigPrettier),
{
rules: {
"@typescript-eslint/no-unused-vars": "warn",
},
},
]);

View File

@@ -9,15 +9,18 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@next/eslint-plugin-next": "^15.1.0", "@next/eslint-plugin-next": "^15.3.3",
"eslint": "^9.15.0", "eslint": "^9.15.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-only-warn": "^1.1.0", "eslint-plugin-only-warn": "^1.1.0",
"eslint-plugin-react": "^7.37.2", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-turbo": "^2.3.0", "eslint-plugin-turbo": "^2.3.0",
"globals": "^15.12.0", "globals": "^15.12.0",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"typescript-eslint": "^8.15.0" "typescript-eslint": "^8.15.0"
},
"dependencies": {
"@typescript-eslint/eslint-plugin": "^8.36.0"
} }
} }

View File

@@ -2,3 +2,5 @@ export * from "./cn";
export * from "./event"; export * from "./event";
export * from "./dates"; export * from "./dates";
export * from "./simulatorConnected"; export * from "./simulatorConnected";
export * from "./useDebounce";
export * from "./useTimeout";

View File

@@ -1,3 +1,4 @@
"use client";
import { DependencyList, useEffect } from "react"; import { DependencyList, useEffect } from "react";
import useTimeout from "./useTimeout"; import useTimeout from "./useTimeout";

View File

@@ -1,3 +1,4 @@
"use client";
import { useCallback, useEffect, useRef } from "react"; import { useCallback, useEffect, useRef } from "react";
export default function useTimeout(callback: () => void, delay: number) { export default function useTimeout(callback: () => void, delay: number) {

View File

@@ -16,5 +16,6 @@
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"target": "ES2022" "target": "ES2022"
} },
"exclude": ["node_modules", "dist", ".next", "out"]
} }

496
pnpm-lock.yaml generated
View File

@@ -7,6 +7,10 @@ settings:
importers: importers:
.: .:
dependencies:
eslint:
specifier: ^9.30.1
version: 9.30.1(jiti@2.4.2)
devDependencies: devDependencies:
prettier: prettier:
specifier: ^3.5.3 specifier: ^3.5.3
@@ -81,6 +85,9 @@ importers:
apps/dispatch: apps/dispatch:
dependencies: dependencies:
'@eslint/eslintrc':
specifier: ^3.3.1
version: 3.3.1
'@hookform/resolvers': '@hookform/resolvers':
specifier: ^5.1.1 specifier: ^5.1.1
version: 5.1.1(react-hook-form@7.59.0(react@19.1.0)) version: 5.1.1(react-hook-form@7.59.0(react@19.1.0))
@@ -147,6 +154,9 @@ importers:
date-fns: date-fns:
specifier: ^4.1.0 specifier: ^4.1.0
version: 4.1.0 version: 4.1.0
eslint-config-next:
specifier: ^15.3.4
version: 15.3.4(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
geojson: geojson:
specifier: ^0.5.0 specifier: ^0.5.0
version: 0.5.0 version: 0.5.0
@@ -325,9 +335,6 @@ importers:
'@catppuccin/vitepress': '@catppuccin/vitepress':
specifier: ^0.1.2 specifier: ^0.1.2
version: 0.1.2(typescript@5.8.3) version: 0.1.2(typescript@5.8.3)
'@repo/typescript-config':
specifier: workspace:*
version: link:../../packages/typescript-config
devDependencies: devDependencies:
vitepress: vitepress:
specifier: ^1.6.3 specifier: ^1.6.3
@@ -398,9 +405,6 @@ importers:
date-fns: date-fns:
specifier: ^4.1.0 specifier: ^4.1.0
version: 4.1.0 version: 4.1.0
eslint:
specifier: ^9.30.0
version: 9.30.0(jiti@2.4.2)
eslint-config-next: eslint-config-next:
specifier: ^15.3.4 specifier: ^15.3.4
version: 15.3.4(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) version: 15.3.4(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
@@ -461,15 +465,25 @@ importers:
tailwindcss: tailwindcss:
specifier: ^4.1.11 specifier: ^4.1.11
version: 4.1.11 version: 4.1.11
typescript:
specifier: ^5.8.3
version: 5.8.3
zod: zod:
specifier: ^3.25.67 specifier: ^3.25.67
version: 3.25.67 version: 3.25.67
zustand: zustand:
specifier: ^5.0.6 specifier: ^5.0.6
version: 5.0.6(@types/react@19.1.8)(react@19.1.0) version: 5.0.6(@types/react@19.1.8)(react@19.1.0)
devDependencies:
'@eslint/js':
specifier: ^9.30.0
version: 9.30.0
eslint:
specifier: ^9.30.0
version: 9.30.0(jiti@2.4.2)
typescript:
specifier: ^5.8.3
version: 5.8.3
typescript-eslint:
specifier: ^8.33.1
version: 8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
apps/hub-server: apps/hub-server:
dependencies: dependencies:
@@ -555,12 +569,16 @@ importers:
version: 6.8.2(typescript@5.8.3) version: 6.8.2(typescript@5.8.3)
packages/eslint-config: packages/eslint-config:
dependencies:
'@typescript-eslint/eslint-plugin':
specifier: ^8.36.0
version: 8.36.0(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
devDependencies: devDependencies:
'@eslint/js': '@eslint/js':
specifier: ^9.17.0 specifier: ^9.17.0
version: 9.28.0 version: 9.28.0
'@next/eslint-plugin-next': '@next/eslint-plugin-next':
specifier: ^15.1.0 specifier: ^15.3.3
version: 15.3.3 version: 15.3.3
eslint: eslint:
specifier: ^9.15.0 specifier: ^9.15.0
@@ -572,10 +590,10 @@ importers:
specifier: ^1.1.0 specifier: ^1.1.0
version: 1.1.0 version: 1.1.0
eslint-plugin-react: eslint-plugin-react:
specifier: ^7.37.2 specifier: ^7.37.5
version: 7.37.5(eslint@9.28.0(jiti@2.4.2)) version: 7.37.5(eslint@9.28.0(jiti@2.4.2))
eslint-plugin-react-hooks: eslint-plugin-react-hooks:
specifier: ^5.0.0 specifier: ^5.2.0
version: 5.2.0(eslint@9.28.0(jiti@2.4.2)) version: 5.2.0(eslint@9.28.0(jiti@2.4.2))
eslint-plugin-turbo: eslint-plugin-turbo:
specifier: ^2.3.0 specifier: ^2.3.0
@@ -1226,6 +1244,10 @@ packages:
resolution: {integrity: sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww==} resolution: {integrity: sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/js@9.30.1':
resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.6': '@eslint/object-schema@2.1.6':
resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2561,11 +2583,11 @@ packages:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/eslint-plugin@8.35.0': '@typescript-eslint/eslint-plugin@8.36.0':
resolution: {integrity: sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==} resolution: {integrity: sha512-lZNihHUVB6ZZiPBNgOQGSxUASI7UJWhT8nHyUGCnaQ28XFCw98IfrMCG3rUl1uwUWoAvodJQby2KTs79UTcrAg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^8.35.0 '@typescript-eslint/parser': ^8.36.0
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
@@ -2595,6 +2617,12 @@ packages:
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/project-service@8.36.0':
resolution: {integrity: sha512-JAhQFIABkWccQYeLMrHadu/fhpzmSQ1F1KXkpzqiVxA/iYI6UnRt2trqXHt1sYEcw1mxLnB9rKMsOxXPxowN/g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/scope-manager@8.33.1': '@typescript-eslint/scope-manager@8.33.1':
resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==} resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2603,6 +2631,10 @@ packages:
resolution: {integrity: sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==} resolution: {integrity: sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/scope-manager@8.36.0':
resolution: {integrity: sha512-wCnapIKnDkN62fYtTGv2+RY8FlnBYA3tNm0fm91kc2BjPhV2vIjwwozJ7LToaLAyb1ca8BxrS7vT+Pvvf7RvqA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.33.1': '@typescript-eslint/tsconfig-utils@8.33.1':
resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==} resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2615,6 +2647,12 @@ packages:
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/tsconfig-utils@8.36.0':
resolution: {integrity: sha512-Nhh3TIEgN18mNbdXpd5Q8mSCBnrZQeY9V7Ca3dqYvNDStNIGRmJA6dmrIPMJ0kow3C7gcQbpsG2rPzy1Ks/AnA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/type-utils@8.33.1': '@typescript-eslint/type-utils@8.33.1':
resolution: {integrity: sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==} resolution: {integrity: sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2622,8 +2660,8 @@ packages:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/type-utils@8.35.0': '@typescript-eslint/type-utils@8.36.0':
resolution: {integrity: sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==} resolution: {integrity: sha512-5aaGYG8cVDd6cxfk/ynpYzxBRZJk7w/ymto6uiyUFtdCozQIsQWh7M28/6r57Fwkbweng8qAzoMCPwSJfWlmsg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
@@ -2637,6 +2675,10 @@ packages:
resolution: {integrity: sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==} resolution: {integrity: sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/types@8.36.0':
resolution: {integrity: sha512-xGms6l5cTJKQPZOKM75Dl9yBfNdGeLRsIyufewnxT4vZTrjC0ImQT4fj8QmtJK84F58uSh5HVBSANwcfiXxABQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.33.1': '@typescript-eslint/typescript-estree@8.33.1':
resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==} resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2649,6 +2691,12 @@ packages:
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/typescript-estree@8.36.0':
resolution: {integrity: sha512-JaS8bDVrfVJX4av0jLpe4ye0BpAaUW7+tnS4Y4ETa3q7NoZgzYbN9zDQTJ8kPb5fQ4n0hliAt9tA4Pfs2zA2Hg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/utils@8.33.1': '@typescript-eslint/utils@8.33.1':
resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==} resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2656,8 +2704,8 @@ packages:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/utils@8.35.0': '@typescript-eslint/utils@8.36.0':
resolution: {integrity: sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==} resolution: {integrity: sha512-VOqmHu42aEMT+P2qYjylw6zP/3E/HvptRwdn/PZxyV27KhZg2IOszXod4NcXisWzPAGSS4trE/g4moNj6XmH2g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
@@ -2671,6 +2719,10 @@ packages:
resolution: {integrity: sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==} resolution: {integrity: sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.36.0':
resolution: {integrity: sha512-vZrhV2lRPWDuGoxcmrzRZyxAggPL+qp3WzUrlZD+slFueDiYHxeBa34dUXPuC0RmGKzl4lS5kFJYvKCq9cnNDA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@uiw/copy-to-clipboard@1.0.17': '@uiw/copy-to-clipboard@1.0.17':
resolution: {integrity: sha512-O2GUHV90Iw2VrSLVLK0OmNIMdZ5fgEg4NhvtwINsX+eZ/Wf6DWD0TdsK9xwV7dNRnK/UI2mQtl0a2/kRgm1m1A==} resolution: {integrity: sha512-O2GUHV90Iw2VrSLVLK0OmNIMdZ5fgEg4NhvtwINsX+eZ/Wf6DWD0TdsK9xwV7dNRnK/UI2mQtl0a2/kRgm1m1A==}
@@ -3694,6 +3746,16 @@ packages:
jiti: jiti:
optional: true optional: true
eslint@9.30.1:
resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
jiti: '*'
peerDependenciesMeta:
jiti:
optional: true
espree@10.3.0: espree@10.3.0:
resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4394,6 +4456,7 @@ packages:
livekit-client@2.14.0: livekit-client@2.14.0:
resolution: {integrity: sha512-+ryoX3bFUNVWTjXsPLnPTW8O9wKUo/ZDPxCPLBeE72Ny0JVIK8QRIW0J/CZbcGCK5VRpYf+jMojKmjlztbSuOg==} resolution: {integrity: sha512-+ryoX3bFUNVWTjXsPLnPTW8O9wKUo/ZDPxCPLBeE72Ny0JVIK8QRIW0J/CZbcGCK5VRpYf+jMojKmjlztbSuOg==}
deprecated: This release is deprecated, update to @latest
peerDependencies: peerDependencies:
'@types/dom-mediacapture-record': ^1 '@types/dom-mediacapture-record': ^1
@@ -6614,6 +6677,11 @@ snapshots:
eslint: 9.30.0(jiti@2.4.2) eslint: 9.30.0(jiti@2.4.2)
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
'@eslint-community/eslint-utils@4.7.0(eslint@9.30.1(jiti@2.4.2))':
dependencies:
eslint: 9.30.1(jiti@2.4.2)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {} '@eslint-community/regexpp@4.12.1': {}
'@eslint/config-array@0.20.0': '@eslint/config-array@0.20.0':
@@ -6662,6 +6730,8 @@ snapshots:
'@eslint/js@9.30.0': {} '@eslint/js@9.30.0': {}
'@eslint/js@9.30.1': {}
'@eslint/object-schema@2.1.6': {} '@eslint/object-schema@2.1.6': {}
'@eslint/plugin-kit@0.3.1': '@eslint/plugin-kit@0.3.1':
@@ -8656,14 +8726,48 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/eslint-plugin@8.35.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/eslint-plugin@8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/scope-manager': 8.33.1
'@typescript-eslint/type-utils': 8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/utils': 8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.33.1
eslint: 9.30.0(jiti@2.4.2)
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/eslint-plugin@8.36.0(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/scope-manager': 8.36.0
'@typescript-eslint/type-utils': 8.36.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/utils': 8.36.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.36.0
eslint: 9.28.0(jiti@2.4.2)
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/eslint-plugin@8.36.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/parser': 8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/scope-manager': 8.35.0 '@typescript-eslint/scope-manager': 8.36.0
'@typescript-eslint/type-utils': 8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/type-utils': 8.36.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/utils': 8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/utils': 8.36.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.35.0 '@typescript-eslint/visitor-keys': 8.36.0
eslint: 9.30.0(jiti@2.4.2) eslint: 9.30.0(jiti@2.4.2)
graphemer: 1.4.0 graphemer: 1.4.0
ignore: 7.0.5 ignore: 7.0.5
@@ -8673,6 +8777,23 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/eslint-plugin@8.36.0(@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/scope-manager': 8.36.0
'@typescript-eslint/type-utils': 8.36.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/utils': 8.36.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.36.0
eslint: 9.30.1(jiti@2.4.2)
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.33.1 '@typescript-eslint/scope-manager': 8.33.1
@@ -8685,6 +8806,18 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.33.1
'@typescript-eslint/types': 8.33.1
'@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.33.1
debug: 4.4.1(supports-color@5.5.0)
eslint: 9.30.0(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.35.0 '@typescript-eslint/scope-manager': 8.35.0
@@ -8697,10 +8830,22 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.35.0
'@typescript-eslint/types': 8.35.0
'@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.35.0
debug: 4.4.1(supports-color@5.5.0)
eslint: 9.30.1(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.33.1(typescript@5.8.3)': '@typescript-eslint/project-service@8.33.1(typescript@5.8.3)':
dependencies: dependencies:
'@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) '@typescript-eslint/tsconfig-utils': 8.36.0(typescript@5.8.3)
'@typescript-eslint/types': 8.33.1 '@typescript-eslint/types': 8.36.0
debug: 4.4.1(supports-color@5.5.0) debug: 4.4.1(supports-color@5.5.0)
typescript: 5.8.3 typescript: 5.8.3
transitivePeerDependencies: transitivePeerDependencies:
@@ -8708,8 +8853,17 @@ snapshots:
'@typescript-eslint/project-service@8.35.0(typescript@5.8.3)': '@typescript-eslint/project-service@8.35.0(typescript@5.8.3)':
dependencies: dependencies:
'@typescript-eslint/tsconfig-utils': 8.35.0(typescript@5.8.3) '@typescript-eslint/tsconfig-utils': 8.36.0(typescript@5.8.3)
'@typescript-eslint/types': 8.35.0 '@typescript-eslint/types': 8.36.0
debug: 4.4.1(supports-color@5.5.0)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.36.0(typescript@5.8.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.36.0(typescript@5.8.3)
'@typescript-eslint/types': 8.36.0
debug: 4.4.1(supports-color@5.5.0) debug: 4.4.1(supports-color@5.5.0)
typescript: 5.8.3 typescript: 5.8.3
transitivePeerDependencies: transitivePeerDependencies:
@@ -8725,6 +8879,11 @@ snapshots:
'@typescript-eslint/types': 8.35.0 '@typescript-eslint/types': 8.35.0
'@typescript-eslint/visitor-keys': 8.35.0 '@typescript-eslint/visitor-keys': 8.35.0
'@typescript-eslint/scope-manager@8.36.0':
dependencies:
'@typescript-eslint/types': 8.36.0
'@typescript-eslint/visitor-keys': 8.36.0
'@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)': '@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)':
dependencies: dependencies:
typescript: 5.8.3 typescript: 5.8.3
@@ -8733,6 +8892,10 @@ snapshots:
dependencies: dependencies:
typescript: 5.8.3 typescript: 5.8.3
'@typescript-eslint/tsconfig-utils@8.36.0(typescript@5.8.3)':
dependencies:
typescript: 5.8.3
'@typescript-eslint/type-utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/type-utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3)
@@ -8744,10 +8907,10 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/type-utils@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/type-utils@8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3) '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3)
'@typescript-eslint/utils': 8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/utils': 8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
debug: 4.4.1(supports-color@5.5.0) debug: 4.4.1(supports-color@5.5.0)
eslint: 9.30.0(jiti@2.4.2) eslint: 9.30.0(jiti@2.4.2)
ts-api-utils: 2.1.0(typescript@5.8.3) ts-api-utils: 2.1.0(typescript@5.8.3)
@@ -8755,10 +8918,45 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/type-utils@8.36.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
'@typescript-eslint/utils': 8.36.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
debug: 4.4.1(supports-color@5.5.0)
eslint: 9.28.0(jiti@2.4.2)
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/type-utils@8.36.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
'@typescript-eslint/utils': 8.36.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
debug: 4.4.1(supports-color@5.5.0)
eslint: 9.30.0(jiti@2.4.2)
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/type-utils@8.36.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
'@typescript-eslint/utils': 8.36.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
debug: 4.4.1(supports-color@5.5.0)
eslint: 9.30.1(jiti@2.4.2)
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@8.33.1': {} '@typescript-eslint/types@8.33.1': {}
'@typescript-eslint/types@8.35.0': {} '@typescript-eslint/types@8.35.0': {}
'@typescript-eslint/types@8.36.0': {}
'@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)': '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)':
dependencies: dependencies:
'@typescript-eslint/project-service': 8.33.1(typescript@5.8.3) '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3)
@@ -8791,6 +8989,22 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/typescript-estree@8.36.0(typescript@5.8.3)':
dependencies:
'@typescript-eslint/project-service': 8.36.0(typescript@5.8.3)
'@typescript-eslint/tsconfig-utils': 8.36.0(typescript@5.8.3)
'@typescript-eslint/types': 8.36.0
'@typescript-eslint/visitor-keys': 8.36.0
debug: 4.4.1(supports-color@5.5.0)
fast-glob: 3.3.3
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.7.2
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2)) '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2))
@@ -8802,17 +9016,50 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/utils@8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0(jiti@2.4.2)) '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0(jiti@2.4.2))
'@typescript-eslint/scope-manager': 8.35.0 '@typescript-eslint/scope-manager': 8.33.1
'@typescript-eslint/types': 8.35.0 '@typescript-eslint/types': 8.33.1
'@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3) '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3)
eslint: 9.30.0(jiti@2.4.2) eslint: 9.30.0(jiti@2.4.2)
typescript: 5.8.3 typescript: 5.8.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.36.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2))
'@typescript-eslint/scope-manager': 8.36.0
'@typescript-eslint/types': 8.36.0
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
eslint: 9.28.0(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.36.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0(jiti@2.4.2))
'@typescript-eslint/scope-manager': 8.36.0
'@typescript-eslint/types': 8.36.0
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
eslint: 9.30.0(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.36.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
'@typescript-eslint/scope-manager': 8.36.0
'@typescript-eslint/types': 8.36.0
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
eslint: 9.30.1(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@8.33.1': '@typescript-eslint/visitor-keys@8.33.1':
dependencies: dependencies:
'@typescript-eslint/types': 8.33.1 '@typescript-eslint/types': 8.33.1
@@ -8823,6 +9070,11 @@ snapshots:
'@typescript-eslint/types': 8.35.0 '@typescript-eslint/types': 8.35.0
eslint-visitor-keys: 4.2.1 eslint-visitor-keys: 4.2.1
'@typescript-eslint/visitor-keys@8.36.0':
dependencies:
'@typescript-eslint/types': 8.36.0
eslint-visitor-keys: 4.2.1
'@uiw/copy-to-clipboard@1.0.17': {} '@uiw/copy-to-clipboard@1.0.17': {}
'@uiw/react-markdown-preview@5.1.4(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': '@uiw/react-markdown-preview@5.1.4(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
@@ -9905,7 +10157,7 @@ snapshots:
dependencies: dependencies:
'@next/eslint-plugin-next': 15.3.4 '@next/eslint-plugin-next': 15.3.4
'@rushstack/eslint-patch': 1.12.0 '@rushstack/eslint-patch': 1.12.0
'@typescript-eslint/eslint-plugin': 8.35.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/eslint-plugin': 8.36.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/parser': 8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/parser': 8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
eslint: 9.30.0(jiti@2.4.2) eslint: 9.30.0(jiti@2.4.2)
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
@@ -9921,6 +10173,26 @@ snapshots:
- eslint-plugin-import-x - eslint-plugin-import-x
- supports-color - supports-color
eslint-config-next@15.3.4(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3):
dependencies:
'@next/eslint-plugin-next': 15.3.4
'@rushstack/eslint-patch': 1.12.0
'@typescript-eslint/eslint-plugin': 8.36.0(@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/parser': 8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
eslint: 9.30.1(jiti@2.4.2)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.30.1(jiti@2.4.2))
eslint-plugin-react: 7.37.5(eslint@9.30.1(jiti@2.4.2))
eslint-plugin-react-hooks: 5.2.0(eslint@9.30.1(jiti@2.4.2))
optionalDependencies:
typescript: 5.8.3
transitivePeerDependencies:
- eslint-import-resolver-webpack
- eslint-plugin-import-x
- supports-color
eslint-config-prettier@9.1.0(eslint@9.28.0(jiti@2.4.2)): eslint-config-prettier@9.1.0(eslint@9.28.0(jiti@2.4.2)):
dependencies: dependencies:
eslint: 9.28.0(jiti@2.4.2) eslint: 9.28.0(jiti@2.4.2)
@@ -9948,6 +10220,21 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.1(supports-color@5.5.0)
eslint: 9.30.1(jiti@2.4.2)
get-tsconfig: 4.10.1
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.14
unrs-resolver: 1.9.2
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2))
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.0(jiti@2.4.2)): eslint-module-utils@2.12.1(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.0(jiti@2.4.2)):
dependencies: dependencies:
debug: 3.2.7 debug: 3.2.7
@@ -9959,6 +10246,17 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
eslint: 9.30.1(jiti@2.4.2)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2))
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.0(jiti@2.4.2)): eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.0(jiti@2.4.2)):
dependencies: dependencies:
'@rtsao/scc': 1.1.0 '@rtsao/scc': 1.1.0
@@ -9988,6 +10286,35 @@ snapshots:
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
- supports-color - supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
array.prototype.findlastindex: 1.2.6
array.prototype.flat: 1.3.3
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
eslint: 9.30.1(jiti@2.4.2)
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
minimatch: 3.1.2
object.fromentries: 2.0.8
object.groupby: 1.0.3
object.values: 1.2.1
semver: 6.3.1
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.35.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
eslint-plugin-jsx-a11y@6.10.2(eslint@9.30.0(jiti@2.4.2)): eslint-plugin-jsx-a11y@6.10.2(eslint@9.30.0(jiti@2.4.2)):
dependencies: dependencies:
aria-query: 5.3.2 aria-query: 5.3.2
@@ -10007,6 +10334,25 @@ snapshots:
safe-regex-test: 1.1.0 safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1 string.prototype.includes: 2.0.1
eslint-plugin-jsx-a11y@6.10.2(eslint@9.30.1(jiti@2.4.2)):
dependencies:
aria-query: 5.3.2
array-includes: 3.1.9
array.prototype.flatmap: 1.3.3
ast-types-flow: 0.0.8
axe-core: 4.10.3
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
eslint: 9.30.1(jiti@2.4.2)
hasown: 2.0.2
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
minimatch: 3.1.2
object.fromentries: 2.0.8
safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1
eslint-plugin-only-warn@1.1.0: {} eslint-plugin-only-warn@1.1.0: {}
eslint-plugin-react-hooks@5.2.0(eslint@9.28.0(jiti@2.4.2)): eslint-plugin-react-hooks@5.2.0(eslint@9.28.0(jiti@2.4.2)):
@@ -10017,6 +10363,10 @@ snapshots:
dependencies: dependencies:
eslint: 9.30.0(jiti@2.4.2) eslint: 9.30.0(jiti@2.4.2)
eslint-plugin-react-hooks@5.2.0(eslint@9.30.1(jiti@2.4.2)):
dependencies:
eslint: 9.30.1(jiti@2.4.2)
eslint-plugin-react@7.37.5(eslint@9.28.0(jiti@2.4.2)): eslint-plugin-react@7.37.5(eslint@9.28.0(jiti@2.4.2)):
dependencies: dependencies:
array-includes: 3.1.9 array-includes: 3.1.9
@@ -10061,6 +10411,28 @@ snapshots:
string.prototype.matchall: 4.0.12 string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0 string.prototype.repeat: 1.0.0
eslint-plugin-react@7.37.5(eslint@9.30.1(jiti@2.4.2)):
dependencies:
array-includes: 3.1.9
array.prototype.findlast: 1.2.5
array.prototype.flatmap: 1.3.3
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
es-iterator-helpers: 1.2.1
eslint: 9.30.1(jiti@2.4.2)
estraverse: 5.3.0
hasown: 2.0.2
jsx-ast-utils: 3.3.5
minimatch: 3.1.2
object.entries: 1.1.9
object.fromentries: 2.0.8
object.values: 1.2.1
prop-types: 15.8.1
resolve: 2.0.0-next.5
semver: 6.3.1
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
eslint-plugin-turbo@2.5.4(eslint@9.28.0(jiti@2.4.2))(turbo@2.5.4): eslint-plugin-turbo@2.5.4(eslint@9.28.0(jiti@2.4.2))(turbo@2.5.4):
dependencies: dependencies:
dotenv: 16.0.3 dotenv: 16.0.3
@@ -10172,6 +10544,48 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint@9.30.1(jiti@2.4.2):
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.21.0
'@eslint/config-helpers': 0.3.0
'@eslint/core': 0.14.0
'@eslint/eslintrc': 3.3.1
'@eslint/js': 9.30.1
'@eslint/plugin-kit': 0.3.3
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.3
'@types/estree': 1.0.8
'@types/json-schema': 7.0.15
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.6
debug: 4.4.1(supports-color@5.5.0)
escape-string-regexp: 4.0.0
eslint-scope: 8.4.0
eslint-visitor-keys: 4.2.1
espree: 10.4.0
esquery: 1.6.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
file-entry-cache: 8.0.0
find-up: 5.0.0
glob-parent: 6.0.2
ignore: 5.3.2
imurmurhash: 0.1.4
is-glob: 4.0.3
json-stable-stringify-without-jsonify: 1.0.1
lodash.merge: 4.6.2
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.4
optionalDependencies:
jiti: 2.4.2
transitivePeerDependencies:
- supports-color
espree@10.3.0: espree@10.3.0:
dependencies: dependencies:
acorn: 8.14.1 acorn: 8.14.1
@@ -12710,6 +13124,16 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
typescript-eslint@8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/parser': 8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
'@typescript-eslint/utils': 8.33.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)
eslint: 9.30.0(jiti@2.4.2)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
typescript@5.8.3: {} typescript@5.8.3: {}
uid2@1.0.0: {} uid2@1.0.0: {}