fix(frontend): shrink callback jargon and harden contract tests

cognitive committed Mar 4, 2026 at 06:15 UTC 197e7abe7661a8613cb7898b285640abdff20dc9
3 files changed +155 -209
cmd/relay-server/frontend/src/components/ServerListView.tsx
+31 -62
@@ -1,4 +1,4 @@
1 -import { useCallback, useEffect, useMemo, useState } from "react";
1 +import { useEffect, useMemo, useState } from "react";
2 import { Header } from "@/components/Header";
3 import { SearchBar } from "@/components/SearchBar";
4 import { ServerCard } from "@/components/ServerCard";
@@ -59,6 +59,20 @@ function toAdminServer(server: ListServer): AdminServer | undefined {
59 return isAdminServer(server) ? server : undefined;
60 }
61
62 +function wrapAdminHandler<Args extends unknown[]>(
63 + handler?: (...args: Args) => void | Promise<void>
64 +): ((...args: Args) => void) | undefined {
65 + if (!handler) {
66 + return undefined;
67 + }
68 +
69 + return (...args: Args) => {
70 + void Promise.resolve(handler(...args)).catch((error) => {
71 + console.error("Failed admin action", error);
72 + });
73 + };
74 +}
75 +
76 export function ServerListView({
77 title = "PORTAL",
78 searchQuery,
@@ -175,74 +189,29 @@ export function ServerListView({
189 }
190 };
191
178 - const triggerBulkAction = async (handler?: (leaseIds: string[]) => void) => {
192 + const runBulkAction = (handler?: (leaseIds: string[]) => void) => {
193 if (!handler || selectedLeaseIds.size === 0) {
194 return;
195 }
196
183 - try {
184 - await Promise.resolve(handler(Array.from(selectedLeaseIds)));
185 - handleClearSelection();
186 - } catch (err) {
187 - console.error("Failed bulk admin action", err);
188 - }
189 - };
190 -
191 - const handleBulkApprove = () => triggerBulkAction(onBulkApprove);
192 - const handleBulkDeny = () => triggerBulkAction(onBulkDeny);
193 - const handleBulkBan = () => triggerBulkAction(onBulkBan);
194 -
195 - const invokeAsyncHandler = useCallback(
196 - (action: (() => void | Promise<void>) | undefined) => {
197 - if (!action) {
198 - return;
199 - }
200 - void Promise.resolve(action()).catch((error) => {
201 - console.error("Failed admin action", error);
197 + void Promise.resolve(handler(Array.from(selectedLeaseIds)))
198 + .then(() => {
199 + handleClearSelection();
200 + })
201 + .catch((err) => {
202 + console.error("Failed bulk admin action", err);
203 });
203 - },
204 - []
205 - );
206 -
207 - const handleCardBanStatusChange = useCallback(
208 - (leaseId: string, isBan: boolean) =>
209 - invokeAsyncHandler(
210 - onBanStatusChange ? () => onBanStatusChange(leaseId, isBan) : undefined
211 - ),
212 - [invokeAsyncHandler, onBanStatusChange]
213 - );
214 -
215 - const handleCardBPSChange = useCallback(
216 - (leaseId: string, bps: number) =>
217 - invokeAsyncHandler(onBPSChange ? () => onBPSChange(leaseId, bps) : undefined),
218 - [invokeAsyncHandler, onBPSChange]
219 - );
220 -
221 - const handleCardApproveStatusChange = useCallback(
222 - (leaseId: string, approve: boolean) =>
223 - invokeAsyncHandler(
224 - onApproveStatusChange
225 - ? () => onApproveStatusChange(leaseId, approve)
226 - : undefined
227 - ),
228 - [invokeAsyncHandler, onApproveStatusChange]
229 - );
204 + };
205
231 - const handleCardDenyStatusChange = useCallback(
232 - (leaseId: string, deny: boolean) =>
233 - invokeAsyncHandler(
234 - onDenyStatusChange ? () => onDenyStatusChange(leaseId, deny) : undefined
235 - ),
236 - [invokeAsyncHandler, onDenyStatusChange]
237 - );
206 + const handleBulkApprove = () => runBulkAction(onBulkApprove);
207 + const handleBulkDeny = () => runBulkAction(onBulkDeny);
208 + const handleBulkBan = () => runBulkAction(onBulkBan);
209
239 - const handleCardIPBanStatusChange = useCallback(
240 - (ip: string, isBan: boolean) =>
241 - invokeAsyncHandler(
242 - onIPBanStatusChange ? () => onIPBanStatusChange(ip, isBan) : undefined
243 - ),
244 - [invokeAsyncHandler, onIPBanStatusChange]
245 - );
210 + const handleCardBanStatusChange = wrapAdminHandler(onBanStatusChange);
211 + const handleCardBPSChange = wrapAdminHandler(onBPSChange);
212 + const handleCardApproveStatusChange = wrapAdminHandler(onApproveStatusChange);
213 + const handleCardDenyStatusChange = wrapAdminHandler(onDenyStatusChange);
214 + const handleCardIPBanStatusChange = wrapAdminHandler(onIPBanStatusChange);
215
216 const adminFilterControls = (
217 <>
cmd/relay-server/frontend/src/hooks/useAdmin.ts
+107 -146
@@ -68,13 +68,6 @@ function toAdminErrorMessage(error: unknown, fallback: string): string {
68 return fallback;
69 }
70
71 -function encodeLeaseIDForPath(raw: string): string {
72 - if (!raw) {
73 - throw new Error("Missing lease ID");
74 - }
75 - return encodeLeaseID(raw);
76 -}
77 -
71 function toAdminServer(
72 row: ServerData,
73 index: number,
@@ -172,19 +165,16 @@ export function useAdmin() {
165 );
166 }, [serverData, bannedLeaseSet]);
167
175 - const additionalFilter = useCallback(
176 - (server: AdminServer) => {
177 - switch (banFilter) {
178 - case "banned":
179 - return server.isBanned;
180 - case "active":
181 - return !server.isBanned;
182 - default:
183 - return true;
184 - }
185 - },
186 - [banFilter]
187 - );
168 + const additionalFilter = (server: AdminServer) => {
169 + switch (banFilter) {
170 + case "banned":
171 + return server.isBanned;
172 + case "active":
173 + return !server.isBanned;
174 + default:
175 + return true;
176 + }
177 + };
178
179 const listState = useList({
180 servers,
@@ -192,151 +182,122 @@ export function useAdmin() {
182 additionalFilter,
183 });
184
195 - const runAdminAction = useCallback(
196 - async (action: () => Promise<void>) => {
197 - setError("");
198 - try {
199 - await action();
200 - await fetchData();
201 - } catch (err: unknown) {
202 - const message = toAdminErrorMessage(err, "Action failed");
203 - console.error(err);
204 - setError(message);
205 - throw err;
206 - }
207 - },
208 - [fetchData]
209 - );
185 + const runAdminAction = async (action: () => Promise<void>) => {
186 + setError("");
187 + try {
188 + await action();
189 + await fetchData();
190 + } catch (err: unknown) {
191 + const message = toAdminErrorMessage(err, "Action failed");
192 + console.error(err);
193 + setError(message);
194 + throw err;
195 + }
196 + };
197
211 - const updateLeaseAction = useCallback(
212 - async (peerId: string, action: LeaseAction, enabled: boolean) => {
213 - const encodedLeaseID = encodeLeaseIDForPath(peerId);
214 - const method = enabled ? apiClient.post : apiClient.delete;
215 - await method<LeaseActionResult>(adminLeasePath(encodedLeaseID, action));
216 - },
217 - []
218 - );
198 + const updateLeaseAction = async (
199 + peerId: string,
200 + action: LeaseAction,
201 + enabled: boolean
202 + ) => {
203 + if (!peerId) {
204 + throw new Error("Missing lease ID");
205 + }
206 + const encodedLeaseID = encodeLeaseID(peerId);
207 + const method = enabled ? apiClient.post : apiClient.delete;
208 + await method<LeaseActionResult>(adminLeasePath(encodedLeaseID, action));
209 + };
210
220 - const handleBanFilterChange = useCallback((value: BanFilter) => {
211 + const handleBanFilterChange = (value: BanFilter) => {
212 setBanFilter(value);
222 - }, []);
213 + };
214
224 - const handleBanStatus = useCallback(
225 - (peerId: string, isBan: boolean) =>
226 - runAdminAction(() => updateLeaseAction(peerId, "ban", isBan)),
227 - [runAdminAction, updateLeaseAction]
228 - );
215 + const handleBanStatus = (peerId: string, isBan: boolean) =>
216 + runAdminAction(() => updateLeaseAction(peerId, "ban", isBan));
217
230 - const handleBPSChange = useCallback(
231 - (peerId: string, bps: number) =>
232 - runAdminAction(async () => {
233 - const encodedLeaseID = encodeLeaseIDForPath(peerId);
234 - const normalizedBPS = Math.trunc(bps);
235 - if (!Number.isFinite(normalizedBPS) || normalizedBPS <= 0) {
236 - await apiClient.delete<LeaseActionResult>(
237 - adminLeasePath(encodedLeaseID, "bps")
238 - );
239 - return;
240 - }
241 - await apiClient.post<LeaseActionResult>(adminLeasePath(encodedLeaseID, "bps"), {
242 - bps: normalizedBPS,
243 - });
244 - }),
245 - [runAdminAction]
246 - );
247 -
248 - const handleApprovalModeChange = useCallback(
249 - async (mode: ApprovalMode) => {
250 - await runAdminAction(async () => {
251 - const response = await apiClient.post<SettingsResponse>(
252 - API_PATHS.admin.approvalMode,
253 - { mode }
218 + const handleBPSChange = (peerId: string, bps: number) =>
219 + runAdminAction(async () => {
220 + if (!peerId) {
221 + throw new Error("Missing lease ID");
222 + }
223 + const encodedLeaseID = encodeLeaseID(peerId);
224 + const normalizedBPS = Math.trunc(bps);
225 + if (!Number.isFinite(normalizedBPS) || normalizedBPS <= 0) {
226 + await apiClient.delete<LeaseActionResult>(
227 + adminLeasePath(encodedLeaseID, "bps")
228 );
255 - const nextMode = normalizeApprovalMode(response?.approval_mode ?? mode);
256 - setApprovalMode(nextMode);
229 + return;
230 + }
231 + await apiClient.post<LeaseActionResult>(adminLeasePath(encodedLeaseID, "bps"), {
232 + bps: normalizedBPS,
233 });
258 - },
259 - [runAdminAction]
260 - );
234 + });
235
262 - const handleApproveStatus = useCallback(
263 - (peerId: string, approve: boolean) =>
264 - runAdminAction(() => updateLeaseAction(peerId, "approve", approve)),
265 - [runAdminAction, updateLeaseAction]
266 - );
236 + const handleApprovalModeChange = async (mode: ApprovalMode) => {
237 + await runAdminAction(async () => {
238 + const response = await apiClient.post<SettingsResponse>(
239 + API_PATHS.admin.approvalMode,
240 + { mode }
241 + );
242 + const nextMode = normalizeApprovalMode(response?.approval_mode ?? mode);
243 + setApprovalMode(nextMode);
244 + });
245 + };
246
268 - const handleDenyStatus = useCallback(
269 - (peerId: string, deny: boolean) =>
270 - runAdminAction(() => updateLeaseAction(peerId, "deny", deny)),
271 - [runAdminAction, updateLeaseAction]
272 - );
247 + const handleApproveStatus = (peerId: string, approve: boolean) =>
248 + runAdminAction(() => updateLeaseAction(peerId, "approve", approve));
249
274 - const handleIPBanStatus = useCallback(
275 - (ip: string, isBan: boolean) =>
276 - runAdminAction(async () => {
277 - const normalizedIP = ip.trim();
278 - if (!normalizedIP) {
279 - throw new Error("Missing IP address");
280 - }
281 - if (isBan) {
282 - await apiClient.post<LeaseActionResult>(adminIPBanPath(normalizedIP));
283 - return;
284 - }
285 - await apiClient.delete<LeaseActionResult>(adminIPBanPath(normalizedIP));
286 - }),
287 - [runAdminAction]
288 - );
250 + const handleDenyStatus = (peerId: string, deny: boolean) =>
251 + runAdminAction(() => updateLeaseAction(peerId, "deny", deny));
252
290 - const runBulkLeaseAction = useCallback(
291 - async (peerIds: string[], action: LeaseAction) => {
292 - const normalizedPeerIDs = dedupeStrings(peerIds.filter((peerId) => peerId.length > 0));
293 - if (normalizedPeerIDs.length === 0) {
294 - throw new Error("No valid leases selected");
253 + const handleIPBanStatus = (ip: string, isBan: boolean) =>
254 + runAdminAction(async () => {
255 + const normalizedIP = ip.trim();
256 + if (!normalizedIP) {
257 + throw new Error("Missing IP address");
258 + }
259 + if (isBan) {
260 + await apiClient.post<LeaseActionResult>(adminIPBanPath(normalizedIP));
261 + return;
262 }
263 + await apiClient.delete<LeaseActionResult>(adminIPBanPath(normalizedIP));
264 + });
265
297 - const results = await Promise.allSettled(
298 - normalizedPeerIDs.map((peerId) =>
299 - apiClient.post<LeaseActionResult>(
300 - adminLeasePath(encodeLeaseIDForPath(peerId), action)
301 - )
266 + const runBulkLeaseAction = async (peerIds: string[], action: LeaseAction) => {
267 + const normalizedPeerIDs = dedupeStrings(peerIds.filter((peerId) => peerId.length > 0));
268 + if (normalizedPeerIDs.length === 0) {
269 + throw new Error("No valid leases selected");
270 + }
271 +
272 + const results = await Promise.allSettled(
273 + normalizedPeerIDs.map((peerId) =>
274 + apiClient.post<LeaseActionResult>(
275 + adminLeasePath(encodeLeaseID(peerId), action)
276 )
303 - );
277 + )
278 + );
279
305 - const failed = results.find(
306 - (
307 - result
308 - ): result is PromiseRejectedResult =>
309 - result.status === "rejected"
310 - );
311 - if (failed) {
312 - throw failed.reason instanceof Error
313 - ? failed.reason
314 - : new Error(String(failed.reason));
315 - }
316 - },
317 - []
318 - );
280 + const failed = results.find(
281 + (
282 + result
283 + ): result is PromiseRejectedResult =>
284 + result.status === "rejected"
285 + );
286 + if (failed) {
287 + throw failed.reason instanceof Error
288 + ? failed.reason
289 + : new Error(String(failed.reason));
290 + }
291 + };
292
320 - const handleBulkAction = useCallback(
321 - (peerIds: string[], action: LeaseAction) =>
322 - runAdminAction(() => runBulkLeaseAction(peerIds, action)),
323 - [runAdminAction, runBulkLeaseAction]
324 - );
293 + const handleBulkAction = (peerIds: string[], action: LeaseAction) =>
294 + runAdminAction(() => runBulkLeaseAction(peerIds, action));
295
326 - const handleBulkApprove = useCallback(
327 - (peerIds: string[]) => handleBulkAction(peerIds, "approve"),
328 - [handleBulkAction]
329 - );
296 + const handleBulkApprove = (peerIds: string[]) => handleBulkAction(peerIds, "approve");
297
331 - const handleBulkDeny = useCallback(
332 - (peerIds: string[]) => handleBulkAction(peerIds, "deny"),
333 - [handleBulkAction]
334 - );
298 + const handleBulkDeny = (peerIds: string[]) => handleBulkAction(peerIds, "deny");
299
336 - const handleBulkBan = useCallback(
337 - (peerIds: string[]) => handleBulkAction(peerIds, "ban"),
338 - [handleBulkAction]
339 - );
300 + const handleBulkBan = (peerIds: string[]) => handleBulkAction(peerIds, "ban");
301
302 return {
303 serverData,
cmd/relay-server/frontend/src/lib/apiPaths.test.ts
+17 -1
@@ -1,6 +1,6 @@
1 import { describe, expect, it } from "vitest";
2
3 -import { API_PATHS } from "@/lib/apiPaths";
3 +import { API_PATHS, adminLeasePath, encodeLeaseID } from "@/lib/apiPaths";
4
5 describe("API_PATHS contract alignment", () => {
6 it("keeps sdk endpoint paths aligned", () => {
@@ -14,6 +14,22 @@ describe("API_PATHS contract alignment", () => {
14 });
15 });
16
17 + it("encodes lease IDs as base64url path segments", () => {
18 + const leaseId = "peer:legacy/123";
19 + const expected = Buffer.from(leaseId)
20 + .toString("base64")
21 + .replace(/\+/g, "-")
22 + .replace(/\//g, "_")
23 + .replace(/=+$/, "");
24 + const encoded = encodeLeaseID(leaseId);
25 +
26 + expect(encoded).toBe(expected);
27 + expect(encoded).not.toContain("=");
28 + expect(adminLeasePath(encoded, "approve")).toBe(
29 + `${API_PATHS.admin.leases}/${encodeURIComponent(encoded)}/approve`
30 + );
31 + });
32 +
33 it("keeps tunnel installer endpoint aligned", () => {
34 expect(API_PATHS.tunnel).toBe("/tunnel");
35 });