refactor(frontend): remove redundant local aliases

cognitive committed Apr 30, 2026 at 00:08 UTC dbf1a760192d9a7acbadda6495f8f0ffacc6cd00
11 files changed +50 -59
cmd/relay-server/frontend.go
+8 -12
@@ -95,7 +95,14 @@ func (f *Frontend) Handler() *http.ServeMux {
95 mux.HandleFunc(types.PathAssetsPrefix, func(w http.ResponseWriter, r *http.Request) {
96 f.ServeAsset(w, r, strings.TrimPrefix(r.URL.Path, "/"), "")
97 })
98 - for _, assetPath := range frontendRootAssetPaths() {
98 + for _, assetPath := range []string{
99 + "/favicon.ico",
100 + "/favicon.svg",
101 + "/favicon-96x96.png",
102 + "/apple-touch-icon.png",
103 + "/web-app-manifest-192x192.png",
104 + "/web-app-manifest-512x512.png",
105 + } {
106 mux.HandleFunc(assetPath, func(w http.ResponseWriter, r *http.Request) {
107 f.ServeAsset(w, r, strings.TrimPrefix(assetPath, "/"), "")
108 })
@@ -364,17 +371,6 @@ func getContentType(ext string) string {
371 return ""
372 }
373
367 -func frontendRootAssetPaths() []string {
368 - return []string{
369 - "/favicon.ico",
370 - "/favicon.svg",
371 - "/favicon-96x96.png",
372 - "/apple-touch-icon.png",
373 - "/web-app-manifest-192x192.png",
374 - "/web-app-manifest-512x512.png",
375 - }
376 -}
377 -
374 func serveInstallBinary(w http.ResponseWriter, r *http.Request) {
375 if r.Method != http.MethodGet && r.Method != http.MethodHead {
376 w.Header().Set("Allow", http.MethodGet+", "+http.MethodHead)
frontend/src/components/ServerCard.tsx
-2
@@ -59,14 +59,12 @@ export function ServerCard({
59 owner,
60 online,
61 firstSeen,
62 - dns: _dns,
62 navigationPath,
63 navigationState,
64 isFavorite = false,
65 onToggleFavorite,
66 showAdminControls = false,
67 identityKey,
69 - address: _address,
68 isBanned = false,
69 isApproved = false,
70 isDenied = false,
frontend/src/components/ServerListView.tsx
+4 -5
@@ -5,9 +5,9 @@ import { SearchBar } from "@/components/SearchBar";
5 import { ServerCard } from "@/components/ServerCard";
6 import { TagCombobox } from "@/components/TagCombobox";
7 import { TunnelCommandModal } from "@/components/TunnelCommandModal";
8 -import type { ClientServer } from "@/hooks/useServerList";
8 +import type { BaseServer } from "@/hooks/useList";
9 import type { AdminServer, ApprovalMode, UDPSettings, TCPPortSettings } from "@/hooks/useAdmin";
10 -import type { SortOption, StatusFilter } from "@/types/filters";
10 +import type { BanFilter, SortOption, StatusFilter } from "@/types/filters";
11 import { StatusSelect } from "@/components/select/StatusSelect";
12 import { BanStatusButtons } from "@/components/button/BanStatusButtons";
13 import { SortbySelect } from "@/components/select/SortbySelect";
@@ -23,8 +23,7 @@ import {
23 DialogTitle,
24 } from "@/components/ui/dialog";
25
26 -export type BanFilter = "all" | "banned" | "active";
27 -type ListServer = ClientServer | AdminServer;
26 +type ListServer = BaseServer | AdminServer;
27
28 interface RelayDomainResponse {
29 release_version?: string;
@@ -131,7 +130,7 @@ interface ServerListViewProps {
130 sortBy: SortOption;
131 selectedTags: string[];
132 availableTags: string[];
134 - filteredServers: ClientServer[] | AdminServer[];
133 + filteredServers: BaseServer[] | AdminServer[];
134 favorites: string[];
135 onSearchChange: (value: string) => void;
136 onStatusChange: (value: StatusFilter) => void;
frontend/src/components/button/BanStatusButtons.tsx
+2 -2
@@ -1,8 +1,8 @@
1 -import { BanFilter } from "@/components/ServerListView";
1 +import type { BanFilter } from "@/types/filters";
2 import clsx from "clsx";
3
4 interface BanStatusButtonsProps {
5 - banFilter: string;
5 + banFilter: BanFilter;
6 onBanFilterChange: (value: BanFilter) => void;
7 className?: string;
8 }
frontend/src/components/select/SortbySelect.tsx
+6 -3
@@ -5,11 +5,11 @@ import {
5 SelectTrigger,
6 SelectValue,
7 } from "@/components/ui/select";
8 -import { SortOption } from "@/types/filters";
8 +import type { SortOption } from "@/types/filters";
9 import clsx from "clsx";
10
11 interface SortbySelectProps {
12 - sortBy: string;
12 + sortBy: SortOption;
13 onSortByChange: (value: SortOption) => void;
14 hideFiltersOnMobile?: boolean;
15 className?: string;
@@ -21,7 +21,10 @@ export const SortbySelect = ({
21 hideFiltersOnMobile,
22 className,
23 }: SortbySelectProps) => (
24 - <Select value={sortBy} onValueChange={onSortByChange}>
24 + <Select
25 + value={sortBy}
26 + onValueChange={(value) => onSortByChange(value as SortOption)}
27 + >
28 <SelectTrigger
29 className={clsx(
30 "w-37.5 h-10 border-border!",
frontend/src/components/select/StatusSelect.tsx
+6 -3
@@ -5,11 +5,11 @@ import {
5 SelectTrigger,
6 SelectValue,
7 } from "@/components/ui/select";
8 -import { StatusFilter } from "@/types/filters";
8 +import type { StatusFilter } from "@/types/filters";
9 import clsx from "clsx";
10
11 interface StatusSelectProps {
12 - status: string;
12 + status: StatusFilter;
13 onStatusChange: (value: StatusFilter) => void;
14 hideFiltersOnMobile?: boolean;
15 className?: string;
@@ -21,7 +21,10 @@ export const StatusSelect = ({
21 hideFiltersOnMobile,
22 className,
23 }: StatusSelectProps) => (
24 - <Select value={status} onValueChange={onStatusChange}>
24 + <Select
25 + value={status}
26 + onValueChange={(value) => onStatusChange(value as StatusFilter)}
27 + >
28 <SelectTrigger
29 className={clsx(
30 "w-32.5 h-10 border-border!",
frontend/src/hooks/useAdmin.ts
+7 -9
@@ -1,7 +1,7 @@
1 import { useEffect, useMemo, useState } from "react";
2 import type { AdminLeaseData } from "@/hooks/useSSRData";
3 import { useList, type BaseServer } from "@/hooks/useList";
4 -import type { BanFilter } from "@/components/ServerListView";
4 +import type { BanFilter } from "@/types/filters";
5 import {
6 API_PATHS,
7 adminIPBanPath,
@@ -30,8 +30,6 @@ type AdminSnapshotResponse = {
30 tcp_port?: { enabled: boolean; max_leases: number };
31 };
32
33 -type LeaseActionResult = ApprovalModeResponse;
34 -
33 export interface AdminServer extends BaseServer {
34 identityKey: string;
35 address: string;
@@ -267,7 +265,7 @@ export function useAdmin() {
265 ) => {
266 const identity = resolveLeaseIdentity(serverData, identityKey);
267 const method = enabled ? apiClient.post : apiClient.delete;
270 - await method<LeaseActionResult>(
268 + await method<ApprovalModeResponse>(
269 adminLeasePath(identity.name, identity.address, action)
270 );
271 };
@@ -300,12 +298,12 @@ export function useAdmin() {
298 try {
299 await runAdminAction(async () => {
300 if (!Number.isFinite(normalizedBPS) || normalizedBPS <= 0) {
303 - await apiClient.delete<LeaseActionResult>(
301 + await apiClient.delete<ApprovalModeResponse>(
302 adminLeasePath(identity.name, identity.address, "bps")
303 );
304 return;
305 }
308 - await apiClient.post<LeaseActionResult>(
306 + await apiClient.post<ApprovalModeResponse>(
307 adminLeasePath(identity.name, identity.address, "bps"),
308 { bps: normalizedBPS }
309 );
@@ -373,10 +371,10 @@ export function useAdmin() {
371 throw new Error("Missing IP address");
372 }
373 if (isBan) {
376 - await apiClient.post<LeaseActionResult>(adminIPBanPath(normalizedIP));
374 + await apiClient.post<ApprovalModeResponse>(adminIPBanPath(normalizedIP));
375 return;
376 }
379 - await apiClient.delete<LeaseActionResult>(adminIPBanPath(normalizedIP));
377 + await apiClient.delete<ApprovalModeResponse>(adminIPBanPath(normalizedIP));
378 });
379
380 const runBulkLeaseAction = async (identityKeys: string[], action: LeaseAction) => {
@@ -390,7 +388,7 @@ export function useAdmin() {
388 const results = await Promise.allSettled(
389 normalizedIdentityKeys.map((identityKey) => {
390 const identity = resolveLeaseIdentity(serverData, identityKey);
393 - return apiClient.post<LeaseActionResult>(
391 + return apiClient.post<ApprovalModeResponse>(
392 adminLeasePath(identity.name, identity.address, action)
393 );
394 })
frontend/src/hooks/useServerList.ts
+2 -4
@@ -4,9 +4,7 @@ import type { PublicLeaseData } from "@/hooks/useSSRData";
4 import { useList, type BaseServer } from "@/hooks/useList";
5 import { parseLeaseMetadata } from "@/lib/metadata";
6
7 -export type ClientServer = BaseServer;
8 -
9 -function convertSSRDataToServers(ssrData: PublicLeaseData[]): ClientServer[] {
7 +function convertSSRDataToServers(ssrData: PublicLeaseData[]): BaseServer[] {
8 return ssrData.map((row) => {
9 const metadata = parseLeaseMetadata(row.Metadata);
10 const hostname = row.Hostname || "";
@@ -31,7 +29,7 @@ function convertSSRDataToServers(ssrData: PublicLeaseData[]): ClientServer[] {
29 export function useServerList() {
30 const ssrData = useSSRData();
31
34 - const servers: ClientServer[] = useMemo(
32 + const servers: BaseServer[] = useMemo(
33 () => convertSSRDataToServers(ssrData),
34 [ssrData]
35 );
frontend/src/hooks/useTunnelCommand.ts
+9 -11
@@ -56,16 +56,6 @@ function nextTunnelNameShuffleKey(): string {
56 return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
57 }
58
59 -function splitDisplayCommand(command: string, os: TunnelCommandOS) {
60 - const lines = command.split("\n");
61 - const installLineCount = os === "windows" ? 2 : 1;
62 -
63 - return {
64 - installBlock: lines.slice(0, installLineCount).join("\n"),
65 - runBlock: lines.slice(installLineCount).join("\n"),
66 - };
67 -}
68 -
59 interface TunnelCommandExtras {
60 relayUrls?: string[];
61 discovery?: boolean;
@@ -123,7 +113,15 @@ export function useTunnelCommand(extras: TunnelCommandExtras = {}) {
113 [commandOptions]
114 );
115 const { installBlock, runBlock } = useMemo(
126 - () => splitDisplayCommand(displayCommand, os),
116 + () => {
117 + const lines = displayCommand.split("\n");
118 + const installLineCount = os === "windows" ? 2 : 1;
119 +
120 + return {
121 + installBlock: lines.slice(0, installLineCount).join("\n"),
122 + runBlock: lines.slice(installLineCount).join("\n"),
123 + };
124 + },
125 [displayCommand, os]
126 );
127
frontend/src/lib/exposeName.ts
+5 -8
@@ -106,7 +106,11 @@ function normalizeExposeTarget(raw: string): string {
106 if (parsed.hostname === "") {
107 return candidate;
108 }
109 - return formatHostPort(parsed.hostname, parsed.port || "80");
109 + const port = parsed.port || "80";
110 + if (parsed.hostname.includes(":")) {
111 + return `[${parsed.hostname}]:${port}`;
112 + }
113 + return `${parsed.hostname}:${port}`;
114 } catch {
115 return candidate;
116 }
@@ -188,10 +192,3 @@ function fnv1a32(bytes: Uint8Array, seed: number): number {
192 }
193 return hash >>> 0;
194 }
191 -
192 -function formatHostPort(hostname: string, port: string): string {
193 - if (hostname.includes(":")) {
194 - return `[${hostname}]:${port}`;
195 - }
196 - return `${hostname}:${port}`;
197 -}
frontend/src/types/filters.ts
+1
@@ -1,4 +1,5 @@
1 export type StatusFilter = "all" | "online" | "offline";
2 +export type BanFilter = "all" | "banned" | "active";
3
4 export type SortOption =
5 | "default"