const DEFAULT_DEV_SERVER_PORT = 3773;const DEFAULT_DEV_WEB_PORT = 5733;const DEV_SERVER_PORT_GAP = DEFAULT_DEV_WEB_PORT - DEFAULT_DEV_SERVER_PORT;const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]); interface BrowserLocationLike { readonly protocol: string; readonly hostname: string; readonly port: string; readonly origin?: string;} interface ResolveServerConnectionInput { readonly bridgeWsUrl?: string; readonly envWsUrl?: string; readonly isDev: boolean; readonly location: BrowserLocationLike;} function trimToUndefined(value: string | undefined): string | undefined { const trimmed = value?.trim(); return trimmed && trimmed.length > 0 ? trimmed : undefined;} function inferLoopbackDevServerWsUrl(input: ResolveServerConnectionInput): string | null { if (!input.isDev) return null; if (!LOOPBACK_HOSTS.has(input.location.hostname)) return null; const currentPort = Number.parseInt(input.location.port, 10); if (!Number.isInteger(currentPort) || currentPort < DEFAULT_DEV_WEB_PORT) { return null; } const inferredServerPort = currentPort - DEV_SERVER_PORT_GAP; if (inferredServerPort < DEFAULT_DEV_SERVER_PORT) { return null; } const protocol = input.location.protocol === "https:" ? "wss:" : "ws:"; return `${protocol}//${input.location.hostname}:${String(inferredServerPort)}`;} export function resolveServerWsUrlFromInput(input: ResolveServerConnectionInput): string { const bridgeWsUrl = trimToUndefined(input.bridgeWsUrl); if (bridgeWsUrl) { return bridgeWsUrl; } const envWsUrl = trimToUndefined(input.envWsUrl); if (envWsUrl) { return envWsUrl; } const inferredDevServerWsUrl = inferLoopbackDevServerWsUrl(input); if (inferredDevServerWsUrl) { return inferredDevServerWsUrl; } const protocol = input.location.protocol === "https:" ? "wss:" : "ws:"; const port = input.location.port.length > 0 ? `:${input.location.port}` : ""; return `${protocol}//${input.location.hostname}${port}`;} export function resolveServerHttpOriginFromInput(input: ResolveServerConnectionInput): string { const fallbackOrigin = input.location.origin ?? `${input.location.protocol}//${input.location.hostname}${input.location.port ? `:${input.location.port}` : ""}`; try { const wsUrl = new URL(resolveServerWsUrlFromInput(input)); const protocol = wsUrl.protocol === "wss:" ? "https:" : wsUrl.protocol === "ws:" ? "http:" : wsUrl.protocol; return `${protocol}//${wsUrl.host}`; } catch { return fallbackOrigin; }} function getCurrentInput(): ResolveServerConnectionInput | null { if (typeof window === "undefined") { return null; } const bridgeWsUrl = window.desktopBridge?.getWsUrl?.() ?? undefined; const envWsUrl = (import.meta.env.VITE_WS_URL as string | undefined) ?? undefined; return { ...(bridgeWsUrl ? { bridgeWsUrl } : {}), ...(envWsUrl ? { envWsUrl } : {}), isDev: import.meta.env.DEV, location: window.location, };} export function resolveServerWsUrl(): string { const input = getCurrentInput(); return input ? resolveServerWsUrlFromInput(input) : "";} export function resolveServerHttpOrigin(): string { const input = getCurrentInput(); return input ? resolveServerHttpOriginFromInput(input) : "";}
const DEFAULT_DEV_SERVER_PORT = 3773;
const DEFAULT_DEV_WEB_PORT = 5733;
const DEV_SERVER_PORT_GAP = DEFAULT_DEV_WEB_PORT - DEFAULT_DEV_SERVER_PORT;
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
interface BrowserLocationLike {
readonly protocol: string;
readonly hostname: string;
readonly port: string;
readonly origin?: string;
}
interface ResolveServerConnectionInput {
readonly bridgeWsUrl?: string;
readonly envWsUrl?: string;
readonly isDev: boolean;
readonly location: BrowserLocationLike;
}
function trimToUndefined(value: string | undefined): string | undefined {
const trimmed = value?.trim();
return trimmed && trimmed.length > 0 ? trimmed : undefined;
}
function inferLoopbackDevServerWsUrl(input: ResolveServerConnectionInput): string | null {
if (!input.isDev) return null;
if (!LOOPBACK_HOSTS.has(input.location.hostname)) return null;
const currentPort = Number.parseInt(input.location.port, 10);
if (!Number.isInteger(currentPort) || currentPort < DEFAULT_DEV_WEB_PORT) {
return null;
}
const inferredServerPort = currentPort - DEV_SERVER_PORT_GAP;
if (inferredServerPort < DEFAULT_DEV_SERVER_PORT) {
return null;
}
const protocol = input.location.protocol === "https:" ? "wss:" : "ws:";
return `${protocol}//${input.location.hostname}:${String(inferredServerPort)}`;
}
export function resolveServerWsUrlFromInput(input: ResolveServerConnectionInput): string {
const bridgeWsUrl = trimToUndefined(input.bridgeWsUrl);
if (bridgeWsUrl) {
return bridgeWsUrl;
}
const envWsUrl = trimToUndefined(input.envWsUrl);
if (envWsUrl) {
return envWsUrl;
}
const inferredDevServerWsUrl = inferLoopbackDevServerWsUrl(input);
if (inferredDevServerWsUrl) {
return inferredDevServerWsUrl;
}
const protocol = input.location.protocol === "https:" ? "wss:" : "ws:";
const port = input.location.port.length > 0 ? `:${input.location.port}` : "";
return `${protocol}//${input.location.hostname}${port}`;
}
export function resolveServerHttpOriginFromInput(input: ResolveServerConnectionInput): string {
const fallbackOrigin =
input.location.origin ??
`${input.location.protocol}//${input.location.hostname}${input.location.port ? `:${input.location.port}` : ""}`;
try {
const wsUrl = new URL(resolveServerWsUrlFromInput(input));
const protocol =
wsUrl.protocol === "wss:" ? "https:" : wsUrl.protocol === "ws:" ? "http:" : wsUrl.protocol;
return `${protocol}//${wsUrl.host}`;
} catch {
return fallbackOrigin;
}
}
function getCurrentInput(): ResolveServerConnectionInput | null {
if (typeof window === "undefined") {
return null;
}
const bridgeWsUrl = window.desktopBridge?.getWsUrl?.() ?? undefined;
const envWsUrl = (import.meta.env.VITE_WS_URL as string | undefined) ?? undefined;
return {
...(bridgeWsUrl ? { bridgeWsUrl } : {}),
...(envWsUrl ? { envWsUrl } : {}),
isDev: import.meta.env.DEV,
location: window.location,
};
}
export function resolveServerWsUrl(): string {
const input = getCurrentInput();
return input ? resolveServerWsUrlFromInput(input) : "";
}
export function resolveServerHttpOrigin(): string {
const input = getCurrentInput();
return input ? resolveServerHttpOriginFromInput(input) : "";
}