File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -5,7 +5,7 @@ import type { StandardHandler } from '../standard'
55import type {
66 HandleStandardServerPeerMessageOptions ,
77} from '../standard-peer'
8- import { readAsBuffer , resolveMaybeOptionalOptions } from '@orpc/shared'
8+ import { logError , readAsBuffer , resolveMaybeOptionalOptions } from '@orpc/shared'
99import { ServerPeer } from '@orpc/standard-server-peer'
1010import { createServerPeerHandleRequestFn } from '../standard-peer'
1111
@@ -26,10 +26,19 @@ export class WsHandler<T extends Context> {
2626 ? await readAsBuffer ( new Blob ( event . data ) )
2727 : event . data
2828
29- await peer . message (
30- message ,
31- createServerPeerHandleRequestFn ( this . standardHandler , resolveMaybeOptionalOptions ( rest ) ) ,
32- )
29+ try {
30+ await peer . message (
31+ message ,
32+ createServerPeerHandleRequestFn ( this . standardHandler , resolveMaybeOptionalOptions ( rest ) ) ,
33+ )
34+ }
35+ catch ( error ) {
36+ /**
37+ * Users cannot catch errors thrown by this `peer.message`, and node.js may
38+ * crash on unhandled rejections, so we log the error here to prevent that.
39+ */
40+ logError ( error )
41+ }
3342 } )
3443
3544 ws . addEventListener ( 'close' , ( ) => {
Original file line number Diff line number Diff line change 1+ import * as Shared from '@orpc/shared'
12import { encodeRequestMessage , MessageType } from '@orpc/standard-server-peer'
23import { os } from '../../builder'
34import { RPCHandler } from './rpc-handler'
45
6+ const logErrorSpy = vi . spyOn ( Shared , 'logError' ) . mockImplementation ( ( ) => { } )
7+
58describe ( 'rpcHandler' , async ( ) => {
69 let signal : AbortSignal
710
@@ -70,4 +73,14 @@ describe('rpcHandler', async () => {
7073 await vi . waitFor ( ( ) => expect ( signal . aborted ) . toBe ( true ) )
7174 expect ( wss . send ) . not . toHaveBeenCalled ( )
7275 } )
76+
77+ it ( 'logs error on message handler error instead of throwing' , async ( ) => {
78+ onMessage ( {
79+ data : 'invalid message that will cause an error' ,
80+ } )
81+
82+ await vi . waitFor ( ( ) => {
83+ expect ( logErrorSpy ) . toHaveBeenCalledWith ( expect . any ( Error ) )
84+ } )
85+ } )
7386} )
Original file line number Diff line number Diff line change @@ -10,6 +10,7 @@ export * from './id'
1010export * from './interceptor'
1111export * from './iterator'
1212export * from './json'
13+ export * from './log'
1314export * from './object'
1415export * from './otel'
1516export * from './proxy'
Original file line number Diff line number Diff line change 1+ import { logError } from './log'
2+
3+ describe ( 'logError' , ( ) => {
4+ it ( 'should log error to console.error' , ( ) => {
5+ const consoleErrorSpy = vi . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } )
6+ const error = new Error ( 'Test error' )
7+ logError ( error )
8+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( error )
9+ consoleErrorSpy . mockRestore ( )
10+ } )
11+
12+ it ( 'should do nothing if console.error is not available' , ( ) => {
13+ const originalConsoleError = console . error
14+ // @ts -expect-error: Temporarily override console.error for testing
15+ console . error = undefined
16+ const error = new Error ( 'Test error' )
17+ expect ( ( ) => logError ( error ) ) . not . toThrow ( )
18+ // Restore the original console.error function
19+ console . error = originalConsoleError
20+ } )
21+ } )
Original file line number Diff line number Diff line change 1+ export function logError ( error : unknown ) : void {
2+ if ( typeof console === 'object' && typeof console . error === 'function' ) {
3+ console . error ( error )
4+ }
5+ }
You can’t perform that action at this time.
0 commit comments