feat(FN-3400): add native shell connection handoff, plugin management CLI/l
This merge adds a complete plugin management system (FN-3565) with CLI commands, a loader, runner, and dashboard routes, along with project-scoped auth storage (FN-3544), native shell connection support for mobile (FN-3400) spanning onboarding, connection manager, and remote desktop handoff, and ref Fusion-Task-Id: FN-3400
This commit is contained in:
@@ -127,4 +127,16 @@ describe("ipc handlers", () => {
|
||||
expect(onDesktopModeChange).toHaveBeenCalledWith("local");
|
||||
expect(window.webContents.send).toHaveBeenCalledWith("shell:state", expect.any(Object));
|
||||
});
|
||||
|
||||
it("shell:saveProfile rejects invalid URLs", async () => {
|
||||
await registerHandlers();
|
||||
const handler = mocks.ipcHandlers.get("shell:saveProfile");
|
||||
|
||||
await expect(handler?.({}, { name: "Prod", serverUrl: "not-a-url" })).rejects.toThrow(
|
||||
"Server URL must be a valid absolute URL",
|
||||
);
|
||||
await expect(handler?.({}, { name: "Prod", serverUrl: "ftp://fusion.example.com" })).rejects.toThrow(
|
||||
"Server URL must use http or https",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,6 +43,20 @@ function createProfileId(): string {
|
||||
return `profile_${Math.random().toString(36).slice(2, 10)}`;
|
||||
}
|
||||
|
||||
function normalizeServerUrl(serverUrl: string): string {
|
||||
const normalized = serverUrl.trim().replace(/\/$/, "");
|
||||
let parsed: URL;
|
||||
try {
|
||||
parsed = new URL(normalized);
|
||||
} catch {
|
||||
throw new Error("Server URL must be a valid absolute URL");
|
||||
}
|
||||
if (!parsed.protocol || !/^https?:$/.test(parsed.protocol)) {
|
||||
throw new Error("Server URL must use http or https");
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function toShellState(
|
||||
settings: Awaited<ReturnType<typeof readShellSettings>>,
|
||||
localServerState?: DesktopLocalServerState,
|
||||
@@ -113,7 +127,7 @@ export function registerIpcHandlers(mainWindow: BrowserWindow, tray: Tray, optio
|
||||
const nextProfile: ShellConnectionProfile = {
|
||||
id: existing?.id ?? profile.id ?? createProfileId(),
|
||||
name: profile.name.trim(),
|
||||
serverUrl: profile.serverUrl.trim().replace(/\/$/, ""),
|
||||
serverUrl: normalizeServerUrl(profile.serverUrl),
|
||||
authToken: profile.authToken ?? null,
|
||||
createdAt: existing?.createdAt ?? timestamp,
|
||||
updatedAt: timestamp,
|
||||
|
||||
Reference in New Issue
Block a user