fix: replace explicit any types with proper TypeScript types
- Create explicit interfaces for Request extensions (AuthenticatedRequest, RequestWithHeaders) - Add type definitions for WebSocket messages and SSH connection data - Use generic types in DataCrypto methods instead of any return types - Define proper interfaces for file manager data structures - Replace catch block any types with unknown and proper type assertions - Add HostConfig and TabData interfaces for Server component Fixes 32 @typescript-eslint/no-explicit-any violations across 5 files
This commit is contained in:
@@ -23,6 +23,35 @@ import {
|
||||
} from "@/ui/main-axios.ts";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface RecentFileData {
|
||||
id: number;
|
||||
name: string;
|
||||
path: string;
|
||||
lastOpened?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface PinnedFileData {
|
||||
id: number;
|
||||
name: string;
|
||||
path: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface ShortcutData {
|
||||
id: number;
|
||||
name: string;
|
||||
path: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface DirectoryItemData {
|
||||
name: string;
|
||||
path: string;
|
||||
type: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface SidebarItem {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -88,31 +117,37 @@ export function FileManagerSidebar({
|
||||
|
||||
try {
|
||||
const recentData = await getRecentFiles(currentHost.id);
|
||||
const recentItems = recentData.slice(0, 5).map((item: any) => ({
|
||||
id: `recent-${item.id}`,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
type: "recent" as const,
|
||||
lastAccessed: item.lastOpened,
|
||||
}));
|
||||
const recentItems = (recentData as RecentFileData[])
|
||||
.slice(0, 5)
|
||||
.map((item: RecentFileData) => ({
|
||||
id: `recent-${item.id}`,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
type: "recent" as const,
|
||||
lastAccessed: item.lastOpened,
|
||||
}));
|
||||
setRecentItems(recentItems);
|
||||
|
||||
const pinnedData = await getPinnedFiles(currentHost.id);
|
||||
const pinnedItems = pinnedData.map((item: any) => ({
|
||||
id: `pinned-${item.id}`,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
type: "pinned" as const,
|
||||
}));
|
||||
const pinnedItems = (pinnedData as PinnedFileData[]).map(
|
||||
(item: PinnedFileData) => ({
|
||||
id: `pinned-${item.id}`,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
type: "pinned" as const,
|
||||
}),
|
||||
);
|
||||
setPinnedItems(pinnedItems);
|
||||
|
||||
const shortcutData = await getFolderShortcuts(currentHost.id);
|
||||
const shortcutItems = shortcutData.map((item: any) => ({
|
||||
id: `shortcut-${item.id}`,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
type: "shortcut" as const,
|
||||
}));
|
||||
const shortcutItems = (shortcutData as ShortcutData[]).map(
|
||||
(item: ShortcutData) => ({
|
||||
id: `shortcut-${item.id}`,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
type: "shortcut" as const,
|
||||
}),
|
||||
);
|
||||
setShortcuts(shortcutItems);
|
||||
} catch (error) {
|
||||
console.error("Failed to load quick access data:", error);
|
||||
@@ -230,12 +265,12 @@ export function FileManagerSidebar({
|
||||
try {
|
||||
const response = await listSSHFiles(sshSessionId, "/");
|
||||
|
||||
const rootFiles = response.files || [];
|
||||
const rootFiles = (response.files || []) as DirectoryItemData[];
|
||||
const rootFolders = rootFiles.filter(
|
||||
(item: any) => item.type === "directory",
|
||||
(item: DirectoryItemData) => item.type === "directory",
|
||||
);
|
||||
|
||||
const rootTreeItems = rootFolders.map((folder: any) => ({
|
||||
const rootTreeItems = rootFolders.map((folder: DirectoryItemData) => ({
|
||||
id: `folder-${folder.name}`,
|
||||
name: folder.name,
|
||||
path: folder.path,
|
||||
@@ -298,12 +333,12 @@ export function FileManagerSidebar({
|
||||
try {
|
||||
const subResponse = await listSSHFiles(sshSessionId, folderPath);
|
||||
|
||||
const subFiles = subResponse.files || [];
|
||||
const subFiles = (subResponse.files || []) as DirectoryItemData[];
|
||||
const subFolders = subFiles.filter(
|
||||
(item: any) => item.type === "directory",
|
||||
(item: DirectoryItemData) => item.type === "directory",
|
||||
);
|
||||
|
||||
const subTreeItems = subFolders.map((folder: any) => ({
|
||||
const subTreeItems = subFolders.map((folder: DirectoryItemData) => ({
|
||||
id: `folder-${folder.path.replace(/\//g, "-")}`,
|
||||
name: folder.name,
|
||||
path: folder.path,
|
||||
|
||||
@@ -27,8 +27,28 @@ import {
|
||||
SystemWidget,
|
||||
} from "./widgets";
|
||||
|
||||
interface HostConfig {
|
||||
id: number;
|
||||
name: string;
|
||||
ip: string;
|
||||
username: string;
|
||||
folder?: string;
|
||||
enableFileManager?: boolean;
|
||||
tunnelConnections?: unknown[];
|
||||
statsConfig?: string | StatsConfig;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface TabData {
|
||||
id: number;
|
||||
type: string;
|
||||
title?: string;
|
||||
hostConfig?: HostConfig;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface ServerProps {
|
||||
hostConfig?: any;
|
||||
hostConfig?: HostConfig;
|
||||
title?: string;
|
||||
isVisible?: boolean;
|
||||
isTopbarOpen?: boolean;
|
||||
@@ -44,7 +64,10 @@ export function Server({
|
||||
}: ServerProps): React.ReactElement {
|
||||
const { t } = useTranslation();
|
||||
const { state: sidebarState } = useSidebar();
|
||||
const { addTab, tabs } = useTabs() as any;
|
||||
const { addTab, tabs } = useTabs() as {
|
||||
addTab: (tab: { type: string; [key: string]: unknown }) => number;
|
||||
tabs: TabData[];
|
||||
};
|
||||
const [serverStatus, setServerStatus] = React.useState<"online" | "offline">(
|
||||
"offline",
|
||||
);
|
||||
@@ -163,13 +186,16 @@ export function Server({
|
||||
if (!cancelled) {
|
||||
setServerStatus(res?.status === "online" ? "online" : "offline");
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (!cancelled) {
|
||||
if (error?.response?.status === 503) {
|
||||
const err = error as {
|
||||
response?: { status?: number };
|
||||
};
|
||||
if (err?.response?.status === 503) {
|
||||
setServerStatus("offline");
|
||||
} else if (error?.response?.status === 504) {
|
||||
} else if (err?.response?.status === 504) {
|
||||
setServerStatus("offline");
|
||||
} else if (error?.response?.status === 404) {
|
||||
} else if (err?.response?.status === 404) {
|
||||
setServerStatus("offline");
|
||||
} else {
|
||||
setServerStatus("offline");
|
||||
@@ -193,14 +219,18 @@ export function Server({
|
||||
});
|
||||
setShowStatsUI(true);
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (!cancelled) {
|
||||
setMetrics(null);
|
||||
setShowStatsUI(false);
|
||||
const err = error as {
|
||||
code?: string;
|
||||
response?: { status?: number; data?: { error?: string } };
|
||||
};
|
||||
if (
|
||||
error?.code === "TOTP_REQUIRED" ||
|
||||
(error?.response?.status === 403 &&
|
||||
error?.response?.data?.error === "TOTP_REQUIRED")
|
||||
err?.code === "TOTP_REQUIRED" ||
|
||||
(err?.response?.status === 403 &&
|
||||
err?.response?.data?.error === "TOTP_REQUIRED")
|
||||
) {
|
||||
toast.error(t("serverStats.totpUnavailable"));
|
||||
} else {
|
||||
@@ -236,7 +266,7 @@ export function Server({
|
||||
const isFileManagerAlreadyOpen = React.useMemo(() => {
|
||||
if (!currentHostConfig) return false;
|
||||
return tabs.some(
|
||||
(tab: any) =>
|
||||
(tab: TabData) =>
|
||||
tab.type === "file_manager" &&
|
||||
tab.hostConfig?.id === currentHostConfig.id,
|
||||
);
|
||||
@@ -291,32 +321,37 @@ export function Server({
|
||||
);
|
||||
setMetrics(data);
|
||||
setShowStatsUI(true);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
const err = error as {
|
||||
code?: string;
|
||||
status?: number;
|
||||
response?: { status?: number; data?: { error?: string } };
|
||||
};
|
||||
if (
|
||||
error?.code === "TOTP_REQUIRED" ||
|
||||
(error?.response?.status === 403 &&
|
||||
error?.response?.data?.error === "TOTP_REQUIRED")
|
||||
err?.code === "TOTP_REQUIRED" ||
|
||||
(err?.response?.status === 403 &&
|
||||
err?.response?.data?.error === "TOTP_REQUIRED")
|
||||
) {
|
||||
toast.error(t("serverStats.totpUnavailable"));
|
||||
setMetrics(null);
|
||||
setShowStatsUI(false);
|
||||
} else if (
|
||||
error?.response?.status === 503 ||
|
||||
error?.status === 503
|
||||
err?.response?.status === 503 ||
|
||||
err?.status === 503
|
||||
) {
|
||||
setServerStatus("offline");
|
||||
setMetrics(null);
|
||||
setShowStatsUI(false);
|
||||
} else if (
|
||||
error?.response?.status === 504 ||
|
||||
error?.status === 504
|
||||
err?.response?.status === 504 ||
|
||||
err?.status === 504
|
||||
) {
|
||||
setServerStatus("offline");
|
||||
setMetrics(null);
|
||||
setShowStatsUI(false);
|
||||
} else if (
|
||||
error?.response?.status === 404 ||
|
||||
error?.status === 404
|
||||
err?.response?.status === 404 ||
|
||||
err?.status === 404
|
||||
) {
|
||||
setServerStatus("offline");
|
||||
setMetrics(null);
|
||||
|
||||
Reference in New Issue
Block a user