1import { AuthSettingsWriteScope } from "@t3tools/contracts";
2import { readEnvironmentScope } from "../../state/session";
3import { useRef, useState } from "react";
4import * as Cause from "effect/Cause";
5import type { SshDeviceHostConfig } from "@t3tools/contracts";
6import { deviceEnvironment } from "../../state/device";
7import { useAtomCommand } from "../../state/use-atom-command";
8import {
9 checkDeviceHostConnections,
10 deviceHostConnectionKey,
11 type DeviceHostCheck,
12 type DeviceHostCheckTarget,
13} from "./deviceHostConnectionChecks";
14
15export function useHostConnectionChecks(targets: ReadonlyArray<DeviceHostCheckTarget>) {
16 const test = useAtomCommand(deviceEnvironment.testHost, { reportFailure: false });
17 const [checks, setChecks] = useState<Record<string, Record<string, DeviceHostCheck>>>({});
18 const running = useRef(new Set<string>());
19 const testConnection = async (host: SshDeviceHostConfig) => {
20 const key = deviceHostConnectionKey(host);
21 if (running.current.has(key)) return;
22 running.current.add(key);
23 setChecks((current) => ({ ...current, [key]: {} }));
24 const results: Record<string, DeviceHostCheck> = {};
25 try {
26 await checkDeviceHostConnections(
27 targets,
28 host,
29 async (environmentId, input) => {
30 if (!readEnvironmentScope(environmentId, AuthSettingsWriteScope)) {
31 throw new Error("This connection cannot test device hosts.");
32 }
33 const result = await test({ environmentId, input });
34 if (result._tag === "Failure") throw new Error(Cause.pretty(result.cause));
35 return result.value;
36 },
37 (environmentId, result) => {
38 results[environmentId] = result;
39 setChecks((current) => ({
40 ...current,
41 [key]: { ...current[key], [environmentId]: result },
42 }));
43 },
44 );
45 return results;
46 } finally {
47 running.current.delete(key);
48 }
49 };
50 return { checks, testConnection };
51}