98 lines · 3.4 KB · TypeScript
RawDownload
import type {  BrowserNavigationTarget,  EnvironmentId,  PreviewUrlResolution,} from "@t3tools/contracts";import { isLoopbackHost, normalizePreviewUrl } from "@t3tools/shared/preview";import { isLocalLoopbackHost, isPrivateNetworkHost } from "@t3tools/shared/hostClassification"; import { readPreparedConnection } from "~/state/session"; export {  normalizeHostname,  isLocalLoopbackHost,  isPrivateNetworkHost,  isPublicFaviconHost,} from "@t3tools/shared/hostClassification"; const readEnvironmentUrl = (environmentId: EnvironmentId): URL => {  const connection = readPreparedConnection(environmentId);  if (!connection) throw new Error(`Environment ${environmentId} is not connected.`);  return new URL(connection.httpBaseUrl);}; const resolveEnvironmentPortTarget = (  environmentId: EnvironmentId,  target: Extract<BrowserNavigationTarget, { readonly kind: "environment-port" }>,  environmentUrl: URL,  requestedUrl?: string,  sourceUrl?: URL,): PreviewUrlResolution => {  if (!isPrivateNetworkHost(environmentUrl.hostname)) {    throw new Error(      "This environment port needs the planned authenticated preview gateway; its server address is not directly private-network reachable.",    );  }  const protocol = target.protocol ?? "http";  const path = target.path?.startsWith("/") ? target.path : `/${target.path ?? ""}`;  const normalizedEnvironmentHost = environmentUrl.hostname.replace(/^\[|\]$/g, "");  // Local loopback environments should advertise `localhost` so Chromium  // dual-stack lookup can reach a Vite server bound only to ::1 or 127.0.0.1.  const resolvedHost = isLocalLoopbackHost(normalizedEnvironmentHost)    ? "localhost"    : normalizedEnvironmentHost.includes(":")      ? `[${normalizedEnvironmentHost}]`      : normalizedEnvironmentHost;  const resolved = sourceUrl    ? new URL(sourceUrl)    : new URL(path, `${protocol}://${resolvedHost}:${target.port}`);  if (sourceUrl) {    resolved.hostname = resolvedHost;    resolved.port = String(target.port);  }  return {    requestedUrl: requestedUrl ?? `${protocol}://localhost:${target.port}${path}`,    resolvedUrl: resolved.toString(),    resolutionKind: isLocalLoopbackHost(normalizedEnvironmentHost)      ? "direct"      : "direct-private-network",    environmentId,  };}; export function resolveBrowserNavigationTarget(  environmentId: EnvironmentId,  target: BrowserNavigationTarget,): PreviewUrlResolution {  if (target.kind === "url") {    return {      requestedUrl: target.url,      resolvedUrl: target.url,      resolutionKind: "direct",      environmentId,    };  }  return resolveEnvironmentPortTarget(environmentId, target, readEnvironmentUrl(environmentId));} export function resolveDiscoveredServerUrl(environmentId: EnvironmentId, rawUrl: string): string {  try {    const normalizedUrl = normalizePreviewUrl(rawUrl);    const parsed = new URL(normalizedUrl);    if (!isLoopbackHost(parsed.hostname)) return normalizedUrl;    return resolveEnvironmentPortTarget(      environmentId,      {        kind: "environment-port",        port: Number(parsed.port || (parsed.protocol === "https:" ? 443 : 80)),        protocol: parsed.protocol === "https:" ? "https" : "http",        path: `${parsed.pathname}${parsed.search}${parsed.hash}`,      },      readEnvironmentUrl(environmentId),      rawUrl,      parsed,    ).resolvedUrl;  } catch {    return rawUrl;  }}