diff --git a/packages/electron-trpc/src/main/__tests__/utils.test.ts b/packages/electron-trpc/src/main/__tests__/utils.test.ts new file mode 100644 index 00000000..e68d6acc --- /dev/null +++ b/packages/electron-trpc/src/main/__tests__/utils.test.ts @@ -0,0 +1,62 @@ +import { describe, test, expect } from 'vitest'; +import { getTRPCErrorFromUnknown } from '../utils'; +import { TRPCError } from '@trpc/server'; + +describe('getTRPCErrorFromUnknown', () => { + test('should return a TRPCError when given a TRPCError', () => { + const error = new TRPCError({ + code: 'TIMEOUT', + cause: new Error('test'), + message: 'test', + }); + const result = getTRPCErrorFromUnknown(error); + + expect(result).toBe(error); + }); + + test('should return a TRPCError when given an Error', () => { + const error = new Error('test'); + const result = getTRPCErrorFromUnknown(error); + + expect(result).toBeInstanceOf(TRPCError); + expect(result).toMatchObject({ + code: 'INTERNAL_SERVER_ERROR', + cause: error, + message: error.message, + }); + }); + + test('should return a TRPCError when given a string', () => { + const error = 'test'; + const result = getTRPCErrorFromUnknown(error); + + expect(result).toBeInstanceOf(TRPCError); + expect(result).toMatchObject({ + code: 'INTERNAL_SERVER_ERROR', + cause: new Error(error), + message: error, + }); + }); + + test('should use the stack from the given error', () => { + const error = new Error('test'); + error.stack = 'test stack'; + const result = getTRPCErrorFromUnknown(error); + + expect(result.stack).toBe(error.stack); + }); + + test.each([{ test: 'test' }, undefined, null])( + 'should fallback to "Unknown error" when given an unknown type', + (error: unknown) => { + const result = getTRPCErrorFromUnknown(error); + + expect(result).toBeInstanceOf(TRPCError); + expect(result).toMatchObject({ + code: 'INTERNAL_SERVER_ERROR', + cause: new Error('Unknown error'), + message: 'Unknown error', + }); + } + ); +}); diff --git a/packages/electron-trpc/src/main/handleIPCMessage.ts b/packages/electron-trpc/src/main/handleIPCMessage.ts index d7347b1e..ae708cac 100644 --- a/packages/electron-trpc/src/main/handleIPCMessage.ts +++ b/packages/electron-trpc/src/main/handleIPCMessage.ts @@ -3,8 +3,9 @@ import type { AnyRouter, inferRouterContext } from '@trpc/server'; import type { TRPCResponseMessage } from '@trpc/server/rpc'; import type { IpcMainEvent } from 'electron'; import { isObservable, Unsubscribable } from '@trpc/server/observable'; +import { transformTRPCResponse } from '@trpc/server/shared'; +import { getTRPCErrorFromUnknown } from './utils'; import { CreateContextOptions } from './types'; -import { getTRPCErrorFromUnknown, transformTRPCResponseItem } from './utils'; import { ELECTRON_TRPC_CHANNEL } from '../constants'; import { ETRPCRequest } from '../types'; @@ -43,7 +44,7 @@ export async function handleIPCMessage({ const respond = (response: TRPCResponseMessage) => { if (event.sender.isDestroyed()) return; - event.reply(ELECTRON_TRPC_CHANNEL, transformTRPCResponseItem(router, response)); + event.reply(ELECTRON_TRPC_CHANNEL, transformTRPCResponse(router, response)); }; try { diff --git a/packages/electron-trpc/src/main/utils.ts b/packages/electron-trpc/src/main/utils.ts index 5bea1221..395c4dff 100644 --- a/packages/electron-trpc/src/main/utils.ts +++ b/packages/electron-trpc/src/main/utils.ts @@ -1,15 +1,12 @@ -import { AnyRouter, TRPCError } from '@trpc/server'; -import { TRPCResponse, TRPCResponseMessage } from '@trpc/server/rpc'; +import { TRPCError } from '@trpc/server'; -// from @trpc/server/src/error/utils +// modified from @trpc/server/src/error/utils export function getTRPCErrorFromUnknown(cause: unknown): TRPCError { - const error = getErrorFromUnknown(cause); - // this should ideally be an `instanceof TRPCError` but for some reason that isn't working - // ref https://github.com/trpc/trpc/issues/331 - if (error.name === 'TRPCError') { - return cause as TRPCError; + if (cause instanceof TRPCError) { + return cause; } + const error = getErrorFromUnknown(cause); const trpcError = new TRPCError({ code: 'INTERNAL_SERVER_ERROR', cause: error, @@ -22,49 +19,15 @@ export function getTRPCErrorFromUnknown(cause: unknown): TRPCError { return trpcError; } -// from @trpc/server/src/error/utils +// modified from @trpc/server/src/error/utils function getErrorFromUnknown(cause: unknown): Error { if (cause instanceof Error) { return cause; } - const message = getMessageFromUnkownError(cause, 'Unknown error'); - return new Error(message); -} - -// from @trpc/server/src/error/utils -function getMessageFromUnkownError(err: unknown, fallback: string): string { - if (typeof err === 'string') { - return err; - } - - if (err instanceof Error && typeof err.message === 'string') { - return err.message; - } - return fallback; -} - -// from @trpc/server/src/internals/transformTRPCResonse -export function transformTRPCResponseItem( - router: AnyRouter, - item: TResponseItem -): TResponseItem { - // explicitly use appRouter instead of router argument: https://github.com/trpc/trpc/issues/2804 - if ('error' in item) { - return { - ...item, - error: router._def._config.transformer.output.serialize(item.error) as unknown, - }; - } - if ('data' in item.result) { - return { - ...item, - result: { - ...item.result, - data: router._def._config.transformer.output.serialize(item.result.data) as unknown, - }, - }; + if (typeof cause === 'string') { + return new Error(cause); } - return item; + return new Error('Unknown error'); }