History

Clarify SSH IPC error presentation

Julius Marminge committed 4 months ago

Commit 477a96f1 parent 19550842 files · +20 −5Browse files

Unified · Split

2 files
  1. apps/desktop/src/ipc/methods/sshEnvironment.test.ts +14 −2
  2. apps/desktop/src/ipc/methods/sshEnvironment.ts +6 −3
apps/desktop/src/ipc/methods/sshEnvironment.test.ts+14−2
@@ -5,6 +5,7 @@ import { · 4 unmodified lines
5} from "@t3tools/contracts";5} from "@t3tools/contracts";
6import {6import {
7 SshCommandSpawnError,7 SshCommandSpawnError,
8 SshCommandTimeoutError,
8 SshHttpBridgeError,9 SshHttpBridgeError,
9 SshPasswordPromptError,10 SshPasswordPromptError,
10} from "@t3tools/ssh/errors";11} from "@t3tools/ssh/errors";
@@ -22,7 +23,7 @@ import { · 11 unmodified lines
22 DesktopSshEnvironmentRequestError,23 DesktopSshEnvironmentRequestError,
23 ensureSshEnvironment,24 ensureSshEnvironment,
24 fetchSshEnvironmentDescriptor,25 fetchSshEnvironmentDescriptor,
25 toDesktopSshOperationPresentationError,26 toDesktopSshIpcPresentationError,
26} from "./sshEnvironment.ts";27} from "./sshEnvironment.ts";
27import * as DesktopSshEnvironment from "../../ssh/DesktopSshEnvironment.ts";28import * as DesktopSshEnvironment from "../../ssh/DesktopSshEnvironment.ts";
28import * as DesktopSshPasswordPrompts from "../../ssh/DesktopSshPasswordPrompts.ts";29import * as DesktopSshPasswordPrompts from "../../ssh/DesktopSshPasswordPrompts.ts";
@@ -102,12 +103,23 @@ describe("SSH environment IPC", () => { · 73 unmodified lines
102 cause,103 cause,
103 });104 });
104 105
105 const presentation = toDesktopSshOperationPresentationError(structured);106 const presentation = toDesktopSshIpcPresentationError(structured);
106 assert.equal(structured.message, "Failed to spawn SSH command for devbox.");107 assert.equal(structured.message, "Failed to spawn SSH command for devbox.");
107 assert.equal(presentation.message, cause.message);108 assert.equal(presentation.message, cause.message);
108 assert.strictEqual(presentation.cause, structured);109 assert.strictEqual(presentation.cause, structured);
109 });110 });
110 111
112 it("passes structural SSH errors without process causes through the IPC boundary", () => {
113 const structured = new SshCommandTimeoutError({
114 command: "ssh",
115 argumentCount: 0,
116 target: "devbox",
117 timeoutMs: 30_000,
118 });
119
120 assert.strictEqual(toDesktopSshIpcPresentationError(structured), structured);
121 });
122
111 it.effect("fetches and decodes the remote environment descriptor", () => {123 it.effect("fetches and decodes the remote environment descriptor", () => {
112 const requestUrls: string[] = [];124 const requestUrls: string[] = [];
113 const layer = makeHttpClientLayer((request) =>125 const layer = makeHttpClientLayer((request) =>
apps/desktop/src/ipc/methods/sshEnvironment.ts+6−3
@@ -73,7 +73,10 @@ const isSshCausePresentationError = Schema.is( · 72 unmodified lines
73 ]),73 ]),
74);74);
75 75
76export function toDesktopSshOperationPresentationError(76// Electron only forwards the message from a rejected ipcRenderer.invoke promise. Keep the typed,
77// structural SSH error intact as the cause for main-process diagnostics while preserving the
78// actionable process message that the renderer historically presented to the user.
79export function toDesktopSshIpcPresentationError(
77 error: DesktopSshEnvironment.DesktopSshEnvironmentOperationError,80 error: DesktopSshEnvironment.DesktopSshEnvironmentOperationError,
78): DesktopSshEnvironment.DesktopSshEnvironmentOperationError | Error {81): DesktopSshEnvironment.DesktopSshEnvironmentOperationError | Error {
79 if (isSshCausePresentationError(error) && error.cause instanceof Error) {82 if (isSshCausePresentationError(error) && error.cause instanceof Error) {
@@ -169,7 +172,7 @@ export const ensureSshEnvironment = DesktopIpc.makeIpcMethod({ · 89 unmodified lines
169 )172 )
170 : Effect.fail(error),173 : Effect.fail(error),
171 }),174 }),
172 Effect.mapError(toDesktopSshOperationPresentationError),175 Effect.mapError(toDesktopSshIpcPresentationError),
173 );176 );
174 }),177 }),
175});178});
@@ -182,7 +185,7 @@ export const disconnectSshEnvironment = DesktopIpc.makeIpcMethod({ · 6 unmodified lines
182 const sshEnvironment = yield* DesktopSshEnvironment.DesktopSshEnvironment;185 const sshEnvironment = yield* DesktopSshEnvironment.DesktopSshEnvironment;
183 yield* sshEnvironment186 yield* sshEnvironment
184 .disconnectEnvironment(target)187 .disconnectEnvironment(target)
185 .pipe(Effect.mapError(toDesktopSshOperationPresentationError));188 .pipe(Effect.mapError(toDesktopSshIpcPresentationError));
186 }),189 }),
187});190});
188 191