diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..40a4775 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,7 @@ +{ + "extends": ["next/core-web-vitals", "next/typescript"], + "rules": { + "@typescript-eslint/no-explicit-any": "off", + "@next/next/no-img-element": "off" + } +} diff --git a/app/(main)/ClientComponents/NetworkChart.tsx b/app/(main)/ClientComponents/NetworkChart.tsx index 45243e1..6256975 100644 --- a/app/(main)/ClientComponents/NetworkChart.tsx +++ b/app/(main)/ClientComponents/NetworkChart.tsx @@ -2,7 +2,6 @@ import NetworkChartLoading from "@/app/(main)/ClientComponents/NetworkChartLoading"; import { NezhaAPIMonitor, ServerMonitorChart } from "@/app/types/nezha-api"; -import { BackIcon } from "@/components/Icon"; import { Card, CardContent, @@ -21,9 +20,7 @@ import { import getEnv from "@/lib/env-entry"; import { formatTime, nezhaFetcher } from "@/lib/utils"; import { formatRelativeTime } from "@/lib/utils"; -import { useLocale } from "next-intl"; import { useTranslations } from "next-intl"; -import { useRouter } from "next/navigation"; import * as React from "react"; import { useCallback, useMemo } from "react"; import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts"; diff --git a/app/(main)/ClientComponents/ServerDetailChartClient.tsx b/app/(main)/ClientComponents/ServerDetailChartClient.tsx index c2fb955..d06c255 100644 --- a/app/(main)/ClientComponents/ServerDetailChartClient.tsx +++ b/app/(main)/ClientComponents/ServerDetailChartClient.tsx @@ -131,7 +131,7 @@ function CpuChart({ data }: { data: NezhaAPISafe }) { } setCpuChartData(newData); } - }, [data]); + }, [data, cpu, cpuChartData]); const chartConfig = { cpu: { @@ -234,7 +234,7 @@ function ProcessChart({ data }: { data: NezhaAPISafe }) { } setProcessChartData(newData); } - }, [data]); + }, [data, process, processChartData]); const chartConfig = { process: { @@ -324,7 +324,7 @@ function MemChart({ data }: { data: NezhaAPISafe }) { } setMemChartData(newData); } - }, [data]); + }, [data, mem, memChartData, swap]); const chartConfig = { mem: { @@ -448,7 +448,7 @@ function DiskChart({ data }: { data: NezhaAPISafe }) { } setDiskChartData(newData); } - }, [data]); + }, [data, disk, diskChartData]); const chartConfig = { disk: { @@ -551,7 +551,7 @@ function NetworkChart({ data }: { data: NezhaAPISafe }) { } setNetworkChartData(newData); } - }, [data]); + }, [data, up, down, networkChartData]); let maxDownload = Math.max(...networkChartData.map((item) => item.download)); maxDownload = Math.ceil(maxDownload); @@ -677,7 +677,7 @@ function ConnectChart({ data }: { data: NezhaAPISafe }) { } setConnectChartData(newData); } - }, [data]); + }, [data, tcp, udp, connectChartData]); const chartConfig = { tcp: { diff --git a/app/(main)/ClientComponents/ServerDetailClient.tsx b/app/(main)/ClientComponents/ServerDetailClient.tsx index ad695bb..98b329a 100644 --- a/app/(main)/ClientComponents/ServerDetailClient.tsx +++ b/app/(main)/ClientComponents/ServerDetailClient.tsx @@ -8,7 +8,7 @@ import { Badge } from "@/components/ui/badge"; import { Card, CardContent } from "@/components/ui/card"; import getEnv from "@/lib/env-entry"; import { cn, formatBytes, nezhaFetcher } from "@/lib/utils"; -import { useLocale, useTranslations } from "next-intl"; +import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import useSWR from "swr"; @@ -51,7 +51,6 @@ export default function ServerDetailClient({ nezhaFetcher, ); const fallbackData = allFallbackData?.result?.find( - // @ts-ignore (item) => item.id === server_id, ); diff --git a/app/(main)/ClientComponents/ServerDetailLoading.tsx b/app/(main)/ClientComponents/ServerDetailLoading.tsx index 1f26be8..7e09fa1 100644 --- a/app/(main)/ClientComponents/ServerDetailLoading.tsx +++ b/app/(main)/ClientComponents/ServerDetailLoading.tsx @@ -1,6 +1,5 @@ import { BackIcon } from "@/components/Icon"; import { Skeleton } from "@/components/ui/skeleton"; -import { useLocale } from "next-intl"; import { useRouter } from "next/navigation"; export function ServerDetailChartLoading() { diff --git a/app/(main)/header.tsx b/app/(main)/header.tsx index 38b5fac..d1dc802 100644 --- a/app/(main)/header.tsx +++ b/app/(main)/header.tsx @@ -61,8 +61,8 @@ function Header() { } // https://github.com/streamich/react-use/blob/master/src/useInterval.ts -const useInterval = (callback: Function, delay?: number | null) => { - const savedCallback = useRef(() => {}); +const useInterval = (callback: () => void, delay: number | null) => { + const savedCallback = useRef<() => void>(() => {}); useEffect(() => { savedCallback.current = callback; }); diff --git a/app/api/detail/route.ts b/app/api/detail/route.ts index 629fc5d..91ee0e6 100644 --- a/app/api/detail/route.ts +++ b/app/api/detail/route.ts @@ -6,6 +6,11 @@ import { NextRequest, NextResponse } from "next/server"; export const dynamic = "force-dynamic"; +interface ResError extends Error { + statusCode: number; + message: string; +} + export async function GET(req: NextRequest) { const session = await auth(); @@ -35,11 +40,10 @@ export async function GET(req: NextRequest) { const detailData = await GetServerDetail({ server_id: serverIdNum }); return NextResponse.json(detailData, { status: 200 }); } catch (error) { - console.error("Error in GET handler:", error); - // @ts-ignore - const statusCode = error.statusCode || 500; - // @ts-ignore - const message = error.message || "Internal Server Error"; + const err = error as ResError; + console.error("Error in GET handler:", err); + const statusCode = err.statusCode || 500; + const message = err.message || "Internal Server Error"; return NextResponse.json({ error: message }, { status: statusCode }); } } diff --git a/app/api/monitor/route.ts b/app/api/monitor/route.ts index b488af0..beb8326 100644 --- a/app/api/monitor/route.ts +++ b/app/api/monitor/route.ts @@ -6,6 +6,11 @@ import { NextRequest, NextResponse } from "next/server"; export const dynamic = "force-dynamic"; +interface ResError extends Error { + statusCode: number; + message: string; +} + export async function GET(req: NextRequest) { const session = await auth(); @@ -36,11 +41,10 @@ export async function GET(req: NextRequest) { }); return NextResponse.json(monitorData, { status: 200 }); } catch (error) { - console.error("Error in GET handler:", error); - // @ts-ignore - const statusCode = error.statusCode || 500; - // @ts-ignore - const message = error.message || "Internal Server Error"; + const err = error as ResError; + console.error("Error in GET handler:", err); + const statusCode = err.statusCode || 500; + const message = err.message || "Internal Server Error"; return NextResponse.json({ error: message }, { status: statusCode }); } } diff --git a/app/api/server/route.ts b/app/api/server/route.ts index 36f9764..f54fdec 100644 --- a/app/api/server/route.ts +++ b/app/api/server/route.ts @@ -2,11 +2,16 @@ import { auth } from "@/auth"; import getEnv from "@/lib/env-entry"; import { GetNezhaData } from "@/lib/serverFetch"; import { redirect } from "next/navigation"; -import { NextRequest, NextResponse } from "next/server"; +import { NextResponse } from "next/server"; export const dynamic = "force-dynamic"; -export async function GET(req: NextRequest) { +interface ResError extends Error { + statusCode: number; + message: string; +} + +export async function GET() { const session = await auth(); if (!session && getEnv("SitePassword")) { @@ -17,11 +22,10 @@ export async function GET(req: NextRequest) { const data = await GetNezhaData(); return NextResponse.json(data, { status: 200 }); } catch (error) { - console.error("Error in GET handler:", error); - // @ts-ignore - const statusCode = error.statusCode || 500; - // @ts-ignore - const message = error.message || "Internal Server Error"; + const err = error as ResError; + console.error("Error in GET handler:", err); + const statusCode = err.statusCode || 500; + const message = err.message || "Internal Server Error"; return NextResponse.json({ error: message }, { status: statusCode }); } } diff --git a/bun.lockb b/bun.lockb index 30ede59..51da8b0 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/ServerCard.tsx b/components/ServerCard.tsx index a54b008..c90d44c 100644 --- a/components/ServerCard.tsx +++ b/components/ServerCard.tsx @@ -10,7 +10,7 @@ import { } from "@/components/ui/popover"; import getEnv from "@/lib/env-entry"; import { cn, formatBytes, formatNezhaInfo } from "@/lib/utils"; -import { useLocale, useTranslations } from "next-intl"; +import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter } from "next/navigation"; @@ -21,7 +21,7 @@ export default function ServerCard({ }) { const t = useTranslations("ServerCard"); const router = useRouter(); - const { id, name, country_code, online, cpu, up, down, mem, stg, ...props } = + const { id, name, country_code, online, cpu, up, down, mem, stg } = formatNezhaInfo(serverInfo); const showFlag = getEnv("NEXT_PUBLIC_ShowFlag") === "true"; diff --git a/components/Switch.tsx b/components/Switch.tsx index e84a080..0d6fbe1 100644 --- a/components/Switch.tsx +++ b/components/Switch.tsx @@ -3,7 +3,7 @@ import { cn } from "@/lib/utils"; import { motion } from "framer-motion"; import { useTranslations } from "next-intl"; -import React, { createRef, useEffect, useRef, useState } from "react"; +import React, { createRef, useEffect, useRef } from "react"; export default function Switch({ allTag, @@ -23,7 +23,7 @@ export default function Switch({ if (savedTag && allTag.includes(savedTag)) { onTagChange(savedTag); } - }, [allTag]); + }, [allTag, onTagChange]); useEffect(() => { const container = scrollRef.current; @@ -53,7 +53,7 @@ export default function Switch({ inline: "center", }); } - }, [nowTag]); + }, [nowTag, allTag]); return (
{ const colorConfig = Object.entries(config).filter( - ([_, config]) => config.theme || config.color, + ([, config]) => config.theme || config.color, ); if (!colorConfig.length) { diff --git a/components/ui/input.tsx b/components/ui/input.tsx index 5b0bce3..6e58d5e 100644 --- a/components/ui/input.tsx +++ b/components/ui/input.tsx @@ -1,8 +1,7 @@ import { cn } from "@/lib/utils"; import * as React from "react"; -export interface InputProps - extends React.InputHTMLAttributes {} +export type InputProps = React.InputHTMLAttributes; const Input = React.forwardRef( ({ className, type, ...props }, ref) => { diff --git a/lib/utils.ts b/lib/utils.ts index 024faf3..17d4186 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -76,9 +76,9 @@ export const nezhaFetcher = async (url: string) => { if (!res.ok) { const error = new Error("An error occurred while fetching the data."); - // @ts-ignore + // @ts-expect-error - res.json() returns a Promise error.info = await res.json(); - // @ts-ignore + // @ts-expect-error - res.status is a number error.status = res.status; throw error; } diff --git a/package.json b/package.json index 0ff9084..f58c2f0 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "sharp": "^0.33.5", "swr": "^2.2.6-beta.4", "tailwind-merge": "^2.5.4", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "typescript-eslint": "^8.12.2" }, "devDependencies": { "eslint-plugin-turbo": "^2.2.3", @@ -68,5 +69,6 @@ "@types/react": "npm:types-react@19.0.0-rc.1", "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", "react-is": "^19.0.0-rc-69d4b800-20241021" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" }