Files
NetMesh/components/HostDetailsPanel.helpers.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

160 lines
4.8 KiB
TypeScript

import type { GroupConfig } from "../domain/models";
import {
findProxyProfile,
hasIncompleteProxyIdentity,
hasMissingProxyIdentity,
hasUnreadableProxyCredential,
isCompleteProxyConfig,
normalizeManualProxyConfig,
} from "../domain/proxyProfiles";
import type { Host, Identity, ProxyConfig, ProxyProfile } from "../types";
import {
LINUX_DISTRO_OPTIONS,
NETWORK_DEVICE_OPTIONS,
POSIX_PLATFORM_OPTIONS,
} from "../domain/host";
export const parseOptionalPortInput = (value: string): number | undefined =>
value ? Number(value) : undefined;
export const resolvePrimaryProtocolSwitchPort = (
currentPort: number | undefined,
nextProtocol: "ssh" | "telnet",
hasGroupTelnetPortDefault: boolean,
hasGroupSshPortDefault: boolean,
): number | undefined => {
if (nextProtocol === "telnet") {
// Don't override if group provides a Telnet default
if (hasGroupTelnetPortDefault || hasGroupSshPortDefault) return currentPort;
if (currentPort === 22 || currentPort === undefined) return 23;
return currentPort;
}
if (nextProtocol === "ssh") {
if (hasGroupSshPortDefault) return currentPort;
if (currentPort === 23 || currentPort === undefined) return 22;
return currentPort;
}
return currentPort;
};
export const resolvePrimaryProtocolSavePort = (
protocol: Host["protocol"],
currentPort: number | undefined,
hasGroupSshPortDefault: boolean,
hasGroupTelnetPortDefault: boolean,
): number | undefined => {
if (protocol === "telnet") {
if (currentPort !== undefined) return currentPort;
if (hasGroupTelnetPortDefault || hasGroupSshPortDefault) return undefined;
return 23;
}
return currentPort ?? (hasGroupSshPortDefault ? undefined : 22);
};
export const resolveDetailsTelnetPort = (
host: Host,
groupDefaults?: Partial<GroupConfig>,
): number => {
if (host.telnetPort !== undefined && host.telnetPort !== null) return host.telnetPort;
if (groupDefaults?.telnetPort !== undefined && groupDefaults.telnetPort !== null) {
return groupDefaults.telnetPort;
}
if (host.protocol === "telnet") {
if (host.port !== undefined && host.port !== null) return host.port;
if (groupDefaults?.port !== undefined && groupDefaults.port !== null) return groupDefaults.port;
}
return 23;
};
export const resolveDetailsTelnetUsername = (
host: Host,
groupDefaults?: Partial<GroupConfig>,
): string =>
host.telnetUsername !== undefined
? host.telnetUsername
: groupDefaults?.telnetUsername !== undefined
? groupDefaults.telnetUsername
: host.username ?? groupDefaults?.username ?? "";
export const resolveDetailsTelnetPassword = (
host: Host,
groupDefaults?: Partial<GroupConfig>,
): string =>
host.telnetPassword !== undefined
? host.telnetPassword
: groupDefaults?.telnetPassword !== undefined
? groupDefaults.telnetPassword
: host.password ?? groupDefaults?.password ?? "";
export const prepareTelnetCredentialsForSave = (host: Host): Host =>
host.telnetIdentityId
? {
...host,
telnetUsername: undefined,
telnetPassword: undefined,
}
: host;
export const LINUX_DISTRO_OPTION_IDS = [
...LINUX_DISTRO_OPTIONS,
...POSIX_PLATFORM_OPTIONS,
...NETWORK_DEVICE_OPTIONS,
];
export type ProxySaveValidationError =
| "required"
| "port"
| "missingSaved"
| "missingIdentity"
| "incompleteIdentity"
| "unreadableIdentity";
export const validateProxyConfigForSave = ({
proxyConfig,
proxyProfileId,
proxyProfiles,
identities,
}: {
proxyConfig?: ProxyConfig;
proxyProfileId?: string;
proxyProfiles?: ProxyProfile[];
identities?: Identity[];
}): ProxySaveValidationError | null => {
const selectedProxyProfile = findProxyProfile(proxyProfileId, proxyProfiles ?? []);
if (proxyProfileId && !selectedProxyProfile) return "missingSaved";
const normalizedProxyConfig = normalizeManualProxyConfig(proxyConfig);
if (normalizedProxyConfig && !isCompleteProxyConfig(normalizedProxyConfig)) {
return normalizedProxyConfig.host ? "port" : "required";
}
const effectiveProxyConfig = selectedProxyProfile?.config ?? proxyConfig;
if (hasMissingProxyIdentity(effectiveProxyConfig, identities ?? [])) {
return "missingIdentity";
}
if (hasIncompleteProxyIdentity(effectiveProxyConfig, identities ?? [])) {
return "incompleteIdentity";
}
if (hasUnreadableProxyCredential(effectiveProxyConfig, identities ?? [])) {
return "unreadableIdentity";
}
return null;
};
export const prepareProxyConfigForSave = (params: {
proxyConfig?: ProxyConfig;
proxyProfileId?: string;
proxyProfiles?: ProxyProfile[];
identities?: Identity[];
}): {
error?: ProxySaveValidationError;
normalizedProxyConfig?: ProxyConfig;
} => {
const error = validateProxyConfigForSave(params);
if (error) return { error };
return {
normalizedProxyConfig: normalizeManualProxyConfig(params.proxyConfig),
};
};