Files
fusion/packages/dashboard/app/shell-native.ts
Fusion 9c484cf19c docs(FN-3408): document shell connection chrome contracts
- Add architecture notes describing shell connection chrome contracts
- Expand dashboard README with shell chrome expectations and integration details
- Add desktop README note aligning desktop shell behavior with documented contracts

Fusion-Task-Id: FN-3408
2026-05-08 00:40:15 -07:00

92 lines
3.2 KiB
TypeScript

import type { ShellHostContext } from "./shell-host";
import type { FusionShellApi, ShellConnectionProfile, ShellConnectionState } from "./types/native-shell";
export interface ShellConnectionNativeResult {
hostKind: ShellHostContext["kind"];
available: boolean;
mode?: "local" | "remote";
profileId?: string;
profileLabel?: string;
serverOrigin?: string;
openConnectionManager: () => Promise<{ ok: true } | { ok: false; reason: "unsupported" | "failed"; error?: string }>;
}
type FusionApiBridge = {
openConnectionManager?: () => Promise<void>;
};
function toOrigin(serverUrl?: string): string | undefined {
if (!serverUrl) return undefined;
try {
return new URL(serverUrl).origin;
} catch {
return undefined;
}
}
function resolveProfile(
state: Pick<ShellConnectionState, "activeProfileId" | "profiles">,
host: ShellHostContext,
): ShellConnectionProfile | null {
const active = state.profiles.find((profile) => profile.id === state.activeProfileId) ?? null;
if (active) return active;
if (host.kind === "browser" || !host.connectionId) return null;
return state.profiles.find((profile) => profile.id === host.connectionId) ?? null;
}
async function readShellState(shellApi?: Pick<FusionShellApi, "getState">): Promise<ShellConnectionState | null> {
if (!shellApi?.getState) return null;
try {
return await shellApi.getState();
} catch {
return null;
}
}
export async function getShellConnectionNativeResult(
host: ShellHostContext,
target: Window & typeof globalThis = window,
): Promise<ShellConnectionNativeResult> {
const fusionApi = (target as Window & { fusionAPI?: FusionApiBridge }).fusionAPI;
const shellApi = (target as Window & { fusionShell?: FusionShellApi }).fusionShell;
const shellState = await readShellState(shellApi);
const profile = shellState ? resolveProfile(shellState, host) : null;
const mode = host.kind === "browser" ? undefined : host.mode ?? shellState?.desktopMode;
const profileId = profile?.id ?? (host.kind === "browser" ? undefined : host.connectionId);
const profileLabel = profile?.name;
const serverOrigin = toOrigin(profile?.serverUrl ?? (host.kind === "browser" ? undefined : host.serverUrl));
const desktopSupported = host.kind === "desktop-shell" && typeof fusionApi?.openConnectionManager === "function";
const mobileSupported = host.kind === "mobile-shell" && typeof shellApi?.openConnectionManager === "function";
const available = desktopSupported || mobileSupported;
return {
hostKind: host.kind,
available,
...(mode ? { mode } : {}),
...(profileId ? { profileId } : {}),
...(profileLabel ? { profileLabel } : {}),
...(serverOrigin ? { serverOrigin } : {}),
openConnectionManager: async () => {
try {
if (desktopSupported) {
await fusionApi.openConnectionManager?.();
return { ok: true };
}
if (mobileSupported) {
await shellApi.openConnectionManager();
return { ok: true };
}
return { ok: false, reason: "unsupported" };
} catch (error) {
return {
ok: false,
reason: "failed",
error: error instanceof Error ? error.message : String(error),
};
}
},
};
}