mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
92 lines
2.6 KiB
TypeScript
92 lines
2.6 KiB
TypeScript
import { parseHostPort } from "@getpaseo/protocol/daemon-endpoints";
|
|
import type { WorkspaceScriptPayload } from "@getpaseo/protocol/messages";
|
|
import type { ActiveConnection } from "@/runtime/host-runtime";
|
|
|
|
export interface ResolvedWorkspaceScriptLink {
|
|
openUrl: string | null;
|
|
labelUrl: string | null;
|
|
}
|
|
|
|
function isLoopbackHost(host: string): boolean {
|
|
const normalizedHost = host.trim().toLowerCase();
|
|
return (
|
|
normalizedHost === "localhost" || normalizedHost === "127.0.0.1" || normalizedHost === "::1"
|
|
);
|
|
}
|
|
|
|
function isLocalOnlyUrl(url: string | null | undefined): boolean {
|
|
if (!url) {
|
|
return true;
|
|
}
|
|
try {
|
|
const parsed = new URL(url);
|
|
const hostname = parsed.hostname.toLowerCase();
|
|
return isLoopbackHost(hostname) || hostname.endsWith(".localhost");
|
|
} catch {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function buildDirectServiceUrl(endpoint: string, port: number): string | null {
|
|
try {
|
|
const { host, isIpv6 } = parseHostPort(endpoint);
|
|
const base = isIpv6 ? `[${host}]` : host;
|
|
return `http://${base}:${port}`;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function resolveWorkspaceScriptLink(input: {
|
|
script: WorkspaceScriptPayload;
|
|
activeConnection: ActiveConnection | null;
|
|
}): ResolvedWorkspaceScriptLink {
|
|
const { script, activeConnection } = input;
|
|
if (script.type !== "service" || script.lifecycle !== "running") {
|
|
return { openUrl: null, labelUrl: null };
|
|
}
|
|
|
|
if (!activeConnection) {
|
|
return { openUrl: null, labelUrl: script.proxyUrl };
|
|
}
|
|
|
|
const localProxyUrl = script.localProxyUrl ?? script.proxyUrl;
|
|
const publicProxyUrl =
|
|
script.publicProxyUrl ?? (!isLocalOnlyUrl(script.proxyUrl) ? script.proxyUrl : null);
|
|
const preferredProxyUrl = publicProxyUrl ?? localProxyUrl ?? script.proxyUrl;
|
|
|
|
if (activeConnection.type === "relay") {
|
|
return {
|
|
openUrl: publicProxyUrl,
|
|
labelUrl: publicProxyUrl ?? localProxyUrl ?? script.proxyUrl,
|
|
};
|
|
}
|
|
|
|
if (activeConnection.type === "directSocket" || activeConnection.type === "directPipe") {
|
|
return { openUrl: localProxyUrl, labelUrl: localProxyUrl };
|
|
}
|
|
|
|
try {
|
|
const { host } = parseHostPort(activeConnection.endpoint);
|
|
if (isLoopbackHost(host)) {
|
|
return { openUrl: localProxyUrl, labelUrl: localProxyUrl };
|
|
}
|
|
} catch {
|
|
return { openUrl: null, labelUrl: preferredProxyUrl };
|
|
}
|
|
|
|
if (publicProxyUrl) {
|
|
return { openUrl: publicProxyUrl, labelUrl: publicProxyUrl };
|
|
}
|
|
|
|
if (script.port === null) {
|
|
return { openUrl: null, labelUrl: script.proxyUrl };
|
|
}
|
|
|
|
const directUrl = buildDirectServiceUrl(activeConnection.endpoint, script.port);
|
|
return {
|
|
openUrl: directUrl,
|
|
labelUrl: directUrl ?? preferredProxyUrl,
|
|
};
|
|
}
|