Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions packages/electron-trpc/src/main/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -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',
});
}
);
});
5 changes: 3 additions & 2 deletions packages/electron-trpc/src/main/handleIPCMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -43,7 +44,7 @@ export async function handleIPCMessage<TRouter extends AnyRouter>({

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 {
Expand Down
55 changes: 9 additions & 46 deletions packages/electron-trpc/src/main/utils.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<TResponseItem extends TRPCResponse | TRPCResponseMessage>(
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');
}