1import type { SshDeviceHostConfig } from "@t3tools/contracts";
2
3/** Apply one host change without replacing another environment's host list. */
4export function updateDeviceHosts(
5 hosts: ReadonlyArray<SshDeviceHostConfig>,
6 host: SshDeviceHostConfig,
7 remove: boolean,
8 original = host,
9): ReadonlyArray<SshDeviceHostConfig> {
10 const sameDestination = (candidate: SshDeviceHostConfig, other: SshDeviceHostConfig) =>
11 candidate.target === other.target &&
12 candidate.port === other.port &&
13 candidate.identityFile === other.identityFile;
14 const findDestination = (destination: SshDeviceHostConfig) => {
15 const matches = hosts.filter((candidate) => sameDestination(candidate, destination));
16 if (matches.length > 1) {
17 throw new Error(
18 "Multiple hosts match this SSH destination. Select the environment to edit its hosts.",
19 );
20 }
21 return matches[0];
22 };
23 // A retry can encounter the updated destination on an environment that
24 // already saved, including one with a different environment-local host ID.
25 const existing =
26 hosts.find((candidate) => candidate.id === original.id) ??
27 findDestination(original) ??
28 (remove ? undefined : findDestination(host));
29 if (remove) return hosts.filter((candidate) => candidate.id !== existing?.id);
30 return existing
31 ? hosts.map((candidate) =>
32 candidate.id === existing.id ? { ...host, id: existing.id } : candidate,
33 )
34 : [...hosts, host];
35}