(
contract: IpcContract<TChannel, TInput, TOutput>,
handler: (
event: IpcMainInvokeEvent,
input: z.infer<TInput>,
) => Promise<z.infer<TOutput>>,
)
| 43 | * }); |
| 44 | */ |
| 45 | export function createTypedHandler< |
| 46 | TChannel extends string, |
| 47 | TInput extends z.ZodType, |
| 48 | TOutput extends z.ZodType, |
| 49 | >( |
| 50 | contract: IpcContract<TChannel, TInput, TOutput>, |
| 51 | handler: ( |
| 52 | event: IpcMainInvokeEvent, |
| 53 | input: z.infer<TInput>, |
| 54 | ) => Promise<z.infer<TOutput>>, |
| 55 | ): void { |
| 56 | registeredHandlers.set(contract.channel, handler); |
| 57 | // Optional chaining: ipcMain is undefined in unit tests (no electron runtime). |
| 58 | ipcMain?.handle( |
| 59 | contract.channel, |
| 60 | async (event: IpcMainInvokeEvent, rawInput: unknown) => { |
| 61 | // Runtime validation of input |
| 62 | const parsed = contract.input.safeParse(rawInput); |
| 63 | if (!parsed.success) { |
| 64 | const errorMessage = parsed.error.issues |
| 65 | .map((e) => `${e.path.join(".")}: ${e.message}`) |
| 66 | .join("; "); |
| 67 | return createIpcErrorEnvelope( |
| 68 | new DyadError( |
| 69 | `[${contract.channel}] Invalid input: ${errorMessage}`, |
| 70 | DyadErrorKind.Validation, |
| 71 | ), |
| 72 | ); |
| 73 | } |
| 74 | |
| 75 | let result: z.infer<TOutput>; |
| 76 | try { |
| 77 | result = await handler(event, parsed.data); |
| 78 | } catch (err) { |
| 79 | sendTelemetryException(err, { ipc_channel: contract.channel }); |
| 80 | return createIpcErrorEnvelope(err); |
| 81 | } |
| 82 | |
| 83 | // Validate output in development mode only (catches handler bugs without prod overhead) |
| 84 | if (process.env.NODE_ENV === "development") { |
| 85 | const outputParsed = contract.output.safeParse(result); |
| 86 | if (!outputParsed.success) { |
| 87 | const errorMessage = outputParsed.error.issues |
| 88 | .map((e) => `${e.path.join(".")}: ${e.message}`) |
| 89 | .join("; "); |
| 90 | console.error( |
| 91 | `[${contract.channel}] Output validation warning: ${errorMessage}`, |
| 92 | ); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | return createIpcSuccessEnvelope(result); |
| 97 | }, |
| 98 | ); |
| 99 | } |
| 100 | |
| 101 | /** |
| 102 | * Creates a typed IPC handler with logging support. |
no test coverage detected