@trpc/server 11.1.0 → 11.1.1-canary.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42,8 +42,8 @@ function fastifyTRPCPlugin(fastify, opts, done) {
42
42
  });
43
43
  fastify.get(prefix ?? '/', {
44
44
  websocket: true
45
- }, async (socket, req)=>{
46
- await onConnection(socket, req.raw);
45
+ }, (socket, req)=>{
46
+ onConnection(socket, req.raw);
47
47
  if (trpcOptions?.keepAlive?.enabled) {
48
48
  const { pingMs, pongWaitMs } = trpcOptions.keepAlive;
49
49
  ws.handleKeepAlive(socket, pingMs, pongWaitMs);
@@ -40,8 +40,8 @@ function fastifyTRPCPlugin(fastify, opts, done) {
40
40
  });
41
41
  fastify.get(prefix ?? '/', {
42
42
  websocket: true
43
- }, async (socket, req)=>{
44
- await onConnection(socket, req.raw);
43
+ }, (socket, req)=>{
44
+ onConnection(socket, req.raw);
45
45
  if (trpcOptions?.keepAlive?.enabled) {
46
46
  const { pingMs, pongWaitMs } = trpcOptions.keepAlive;
47
47
  handleKeepAlive(socket, pingMs, pongWaitMs);
@@ -43,7 +43,7 @@ export type WSSHandlerOptions<TRouter extends AnyRouter> = WSConnectionHandlerOp
43
43
  */
44
44
  dangerouslyDisablePong?: boolean;
45
45
  };
46
- export declare function getWSConnectionHandler<TRouter extends AnyRouter>(opts: WSSHandlerOptions<TRouter>): (client: ws.WebSocket, req: IncomingMessage) => Promise<void>;
46
+ export declare function getWSConnectionHandler<TRouter extends AnyRouter>(opts: WSSHandlerOptions<TRouter>): (client: ws.WebSocket, req: IncomingMessage) => void;
47
47
  /**
48
48
  * Handle WebSocket keep-alive messages
49
49
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/adapters/ws.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAa/D,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AAIxC,OAAO,EAAa,KAAK,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAQ7E;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,8BAA8B,CACpE,eAAe,EACf,EAAE,CAAC,SAAS,CACb,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,CAAC,OAAO,SAAS,SAAS,IAAI,CAC1D,IAAI,EAAE,yBAAyB,KAC5B,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;AAE/C,MAAM,MAAM,0BAA0B,CAAC,OAAO,SAAS,SAAS,IAC9D,kBAAkB,CAAC,OAAO,EAAE,eAAe,CAAC,GAC1C,qBAAqB,CACnB,kBAAkB,CAAC,OAAO,CAAC,EAC3B,kBAAkB,CAAC,OAAO,CAAC,CAC5B,CAAC;AAEN;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,SAAS,IACrD,0BAA0B,CAAC,OAAO,CAAC,GAAG;IACpC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE;QACV;;;WAGG;QACH,OAAO,EAAE,OAAO,CAAC;QACjB;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB;;;WAGG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAGJ,wBAAgB,sBAAsB,CAAC,OAAO,SAAS,SAAS,EAC9D,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAKlB,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,eAAe,mBAmYzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,EAAE,CAAC,SAAS,EACpB,MAAM,SAAS,EACf,UAAU,SAAQ,QAiCnB;AAED,wBAAgB,eAAe,CAAC,OAAO,SAAS,SAAS,EACvD,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC;;EAwCjC"}
1
+ {"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/adapters/ws.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAa/D,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AAMxC,OAAO,EAAa,KAAK,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAQ7E;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,8BAA8B,CACpE,eAAe,EACf,EAAE,CAAC,SAAS,CACb,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,CAAC,OAAO,SAAS,SAAS,IAAI,CAC1D,IAAI,EAAE,yBAAyB,KAC5B,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;AAE/C,MAAM,MAAM,0BAA0B,CAAC,OAAO,SAAS,SAAS,IAC9D,kBAAkB,CAAC,OAAO,EAAE,eAAe,CAAC,GAC1C,qBAAqB,CACnB,kBAAkB,CAAC,OAAO,CAAC,EAC3B,kBAAkB,CAAC,OAAO,CAAC,CAC5B,CAAC;AAEN;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,SAAS,IACrD,0BAA0B,CAAC,OAAO,CAAC,GAAG;IACpC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE;QACV;;;WAGG;QACH,OAAO,EAAE,OAAO,CAAC;QACjB;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB;;;WAGG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEJ,wBAAgB,sBAAsB,CAAC,OAAO,SAAS,SAAS,EAC9D,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAKxB,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,eAAe,UAyanD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,EAAE,CAAC,SAAS,EACpB,MAAM,SAAS,EACf,UAAU,SAAQ,QAiCnB;AAED,wBAAgB,eAAe,CAAC,OAAO,SAAS,SAAS,EACvD,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC;;EAyBjC"}
@@ -84,11 +84,10 @@ function _ts_dispose_resources(env) {
84
84
  * Importing ws causes a build error
85
85
  * @see https://github.com/trpc/trpc/pull/5279
86
86
  */ const WEBSOCKET_OPEN = 1; /* ws.WebSocket.OPEN */
87
- const unsetContextPromiseSymbol = Symbol('unsetContextPromise');
88
87
  function getWSConnectionHandler(opts) {
89
88
  const { createContext, router: router$1 } = opts;
90
89
  const { transformer: transformer$1 } = router$1._def._config;
91
- return async (client, req)=>{
90
+ return (client, req)=>{
92
91
  const clientSubscriptions = new Map();
93
92
  const abortController = new AbortController();
94
93
  if (opts.keepAlive?.enabled) {
@@ -98,23 +97,28 @@ function getWSConnectionHandler(opts) {
98
97
  function respond(untransformedJSON) {
99
98
  client.send(JSON.stringify(transformer.transformTRPCResponse(router$1._def._config, untransformedJSON)));
100
99
  }
101
- function createCtxPromise(getConnectionParams) {
102
- return utils.run(async ()=>{
103
- ctx = await createContext?.({
104
- req,
105
- res: client,
106
- info: {
107
- connectionParams: getConnectionParams(),
108
- calls: [],
109
- isBatchCall: false,
110
- accept: null,
111
- type: 'unknown',
112
- signal: abortController.signal,
113
- url: null
114
- }
100
+ async function createCtxPromise(getConnectionParams) {
101
+ try {
102
+ return await utils.run(async ()=>{
103
+ ctx = await createContext?.({
104
+ req,
105
+ res: client,
106
+ info: {
107
+ connectionParams: getConnectionParams(),
108
+ calls: [],
109
+ isBatchCall: false,
110
+ accept: null,
111
+ type: 'unknown',
112
+ signal: abortController.signal,
113
+ url: null
114
+ }
115
+ });
116
+ return {
117
+ ok: true,
118
+ value: ctx
119
+ };
115
120
  });
116
- return ctx;
117
- }).catch((cause)=>{
121
+ } catch (cause) {
118
122
  const error = TRPCError.getTRPCErrorFromUnknown(cause);
119
123
  opts.onError?.({
120
124
  error,
@@ -139,8 +143,11 @@ function getWSConnectionHandler(opts) {
139
143
  (globalThis.setImmediate ?? globalThis.setTimeout)(()=>{
140
144
  client.close();
141
145
  });
142
- throw error;
143
- });
146
+ return {
147
+ ok: false,
148
+ error
149
+ };
150
+ }
144
151
  }
145
152
  let ctx = undefined;
146
153
  /**
@@ -148,14 +155,35 @@ function getWSConnectionHandler(opts) {
148
155
  *
149
156
  * - the context promise will be created immediately on connection if no connectionParams are expected
150
157
  * - if connection params are expected, they will be created once received
151
- */ let ctxPromise = incomingMessageToRequest.createURL(req).searchParams.get('connectionParams') === '1' ? unsetContextPromiseSymbol : createCtxPromise(()=>null);
152
- async function handleRequest(msg) {
158
+ */ let ctxPromise = incomingMessageToRequest.createURL(req).searchParams.get('connectionParams') === '1' ? null : createCtxPromise(()=>null);
159
+ function handleRequest(msg) {
153
160
  const { id, jsonrpc } = msg;
154
- /* istanbul ignore next -- @preserve */ if (id === null) {
155
- throw new TRPCError.TRPCError({
156
- code: 'BAD_REQUEST',
161
+ if (id === null) {
162
+ const error = TRPCError.getTRPCErrorFromUnknown(new TRPCError.TRPCError({
163
+ code: 'PARSE_ERROR',
157
164
  message: '`id` is required'
165
+ }));
166
+ opts.onError?.({
167
+ error,
168
+ path: undefined,
169
+ type: 'unknown',
170
+ ctx,
171
+ req,
172
+ input: undefined
158
173
  });
174
+ respond({
175
+ id,
176
+ jsonrpc,
177
+ error: getErrorShape.getErrorShape({
178
+ config: router$1._def._config,
179
+ error,
180
+ type: 'unknown',
181
+ path: undefined,
182
+ input: undefined,
183
+ ctx
184
+ })
185
+ });
186
+ return;
159
187
  }
160
188
  if (msg.method === 'subscription.stop') {
161
189
  clientSubscriptions.get(id)?.abort();
@@ -164,20 +192,24 @@ function getWSConnectionHandler(opts) {
164
192
  const { path, lastEventId } = msg.params;
165
193
  let { input } = msg.params;
166
194
  const type = msg.method;
167
- try {
168
- if (lastEventId !== undefined) {
169
- if (utils.isObject(input)) {
170
- input = {
171
- ...input,
172
- lastEventId: lastEventId
173
- };
174
- } else {
175
- input ?? (input = {
176
- lastEventId: lastEventId
177
- });
178
- }
195
+ if (lastEventId !== undefined) {
196
+ if (utils.isObject(input)) {
197
+ input = {
198
+ ...input,
199
+ lastEventId: lastEventId
200
+ };
201
+ } else {
202
+ input ?? (input = {
203
+ lastEventId: lastEventId
204
+ });
205
+ }
206
+ }
207
+ utils.run(async ()=>{
208
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
209
+ const res = await ctxPromise; // asserts context has been set
210
+ if (!res.ok) {
211
+ throw res.error;
179
212
  }
180
- await ctxPromise; // asserts context has been set
181
213
  const abortController = new AbortController();
182
214
  const result = await router.callProcedure({
183
215
  router: router$1,
@@ -345,7 +377,7 @@ function getWSConnectionHandler(opts) {
345
377
  type: 'started'
346
378
  }
347
379
  });
348
- } catch (cause) /* istanbul ignore next -- @preserve */ {
380
+ }).catch((cause)=>{
349
381
  // procedure threw an error
350
382
  const error = TRPCError.getTRPCErrorFromUnknown(cause);
351
383
  opts.onError?.({
@@ -368,9 +400,9 @@ function getWSConnectionHandler(opts) {
368
400
  ctx
369
401
  })
370
402
  });
371
- }
403
+ });
372
404
  }
373
- client.on('message', async (rawData)=>{
405
+ client.on('message', (rawData)=>{
374
406
  // eslint-disable-next-line @typescript-eslint/no-base-to-string
375
407
  const msgStr = rawData.toString();
376
408
  if (msgStr === 'PONG') {
@@ -382,7 +414,7 @@ function getWSConnectionHandler(opts) {
382
414
  }
383
415
  return;
384
416
  }
385
- if (ctxPromise === unsetContextPromiseSymbol) {
417
+ if (!ctxPromise) {
386
418
  // If the ctxPromise wasn't created immediately, we're expecting the first message to be a TRPCConnectionParamsMessage
387
419
  ctxPromise = createCtxPromise(()=>{
388
420
  let msg;
@@ -403,30 +435,33 @@ function getWSConnectionHandler(opts) {
403
435
  });
404
436
  return;
405
437
  }
406
- try {
407
- const msgJSON = JSON.parse(msgStr);
408
- const msgs = Array.isArray(msgJSON) ? msgJSON : [
409
- msgJSON
410
- ];
411
- const promises = msgs.map((raw)=>parseTRPCMessage.parseTRPCMessage(raw, transformer$1)).map(handleRequest);
412
- await Promise.all(promises);
413
- } catch (cause) {
414
- const error = new TRPCError.TRPCError({
415
- code: 'PARSE_ERROR',
416
- cause
417
- });
418
- respond({
419
- id: null,
420
- error: getErrorShape.getErrorShape({
421
- config: router$1._def._config,
422
- error,
423
- type: 'unknown',
424
- path: undefined,
425
- input: undefined,
426
- ctx: undefined
427
- })
428
- });
429
- }
438
+ const parsedMsgs = utils.run(()=>{
439
+ try {
440
+ const msgJSON = JSON.parse(msgStr);
441
+ const msgs = Array.isArray(msgJSON) ? msgJSON : [
442
+ msgJSON
443
+ ];
444
+ return msgs.map((raw)=>parseTRPCMessage.parseTRPCMessage(raw, transformer$1));
445
+ } catch (cause) {
446
+ const error = new TRPCError.TRPCError({
447
+ code: 'PARSE_ERROR',
448
+ cause
449
+ });
450
+ respond({
451
+ id: null,
452
+ error: getErrorShape.getErrorShape({
453
+ config: router$1._def._config,
454
+ error,
455
+ type: 'unknown',
456
+ path: undefined,
457
+ input: undefined,
458
+ ctx
459
+ })
460
+ });
461
+ return [];
462
+ }
463
+ });
464
+ parsedMsgs.map(handleRequest);
430
465
  });
431
466
  // WebSocket errors should be handled, as otherwise unhandled exceptions will crash Node.js.
432
467
  // This line was introduced after the following error brought down production systems:
@@ -449,9 +484,6 @@ function getWSConnectionHandler(opts) {
449
484
  clientSubscriptions.clear();
450
485
  abortController.abort();
451
486
  });
452
- if (ctxPromise !== unsetContextPromiseSymbol) {
453
- await ctxPromise;
454
- }
455
487
  };
456
488
  }
457
489
  /**
@@ -488,21 +520,7 @@ function applyWSSHandler(opts) {
488
520
  if (opts.prefix && !req.url?.startsWith(opts.prefix)) {
489
521
  return;
490
522
  }
491
- onConnection(client, req).catch((cause)=>{
492
- opts.onError?.({
493
- error: new TRPCError.TRPCError({
494
- code: 'INTERNAL_SERVER_ERROR',
495
- cause,
496
- message: 'Failed to handle WebSocket connection'
497
- }),
498
- req: req,
499
- path: undefined,
500
- type: 'unknown',
501
- ctx: undefined,
502
- input: undefined
503
- });
504
- client.close();
505
- });
523
+ onConnection(client, req);
506
524
  });
507
525
  return {
508
526
  broadcastReconnectNotification: ()=>{
@@ -82,11 +82,10 @@ function _ts_dispose_resources(env) {
82
82
  * Importing ws causes a build error
83
83
  * @see https://github.com/trpc/trpc/pull/5279
84
84
  */ const WEBSOCKET_OPEN = 1; /* ws.WebSocket.OPEN */
85
- const unsetContextPromiseSymbol = Symbol('unsetContextPromise');
86
85
  function getWSConnectionHandler(opts) {
87
86
  const { createContext, router } = opts;
88
87
  const { transformer } = router._def._config;
89
- return async (client, req)=>{
88
+ return (client, req)=>{
90
89
  const clientSubscriptions = new Map();
91
90
  const abortController = new AbortController();
92
91
  if (opts.keepAlive?.enabled) {
@@ -96,23 +95,28 @@ function getWSConnectionHandler(opts) {
96
95
  function respond(untransformedJSON) {
97
96
  client.send(JSON.stringify(transformTRPCResponse(router._def._config, untransformedJSON)));
98
97
  }
99
- function createCtxPromise(getConnectionParams) {
100
- return run(async ()=>{
101
- ctx = await createContext?.({
102
- req,
103
- res: client,
104
- info: {
105
- connectionParams: getConnectionParams(),
106
- calls: [],
107
- isBatchCall: false,
108
- accept: null,
109
- type: 'unknown',
110
- signal: abortController.signal,
111
- url: null
112
- }
98
+ async function createCtxPromise(getConnectionParams) {
99
+ try {
100
+ return await run(async ()=>{
101
+ ctx = await createContext?.({
102
+ req,
103
+ res: client,
104
+ info: {
105
+ connectionParams: getConnectionParams(),
106
+ calls: [],
107
+ isBatchCall: false,
108
+ accept: null,
109
+ type: 'unknown',
110
+ signal: abortController.signal,
111
+ url: null
112
+ }
113
+ });
114
+ return {
115
+ ok: true,
116
+ value: ctx
117
+ };
113
118
  });
114
- return ctx;
115
- }).catch((cause)=>{
119
+ } catch (cause) {
116
120
  const error = getTRPCErrorFromUnknown(cause);
117
121
  opts.onError?.({
118
122
  error,
@@ -137,8 +141,11 @@ function getWSConnectionHandler(opts) {
137
141
  (globalThis.setImmediate ?? globalThis.setTimeout)(()=>{
138
142
  client.close();
139
143
  });
140
- throw error;
141
- });
144
+ return {
145
+ ok: false,
146
+ error
147
+ };
148
+ }
142
149
  }
143
150
  let ctx = undefined;
144
151
  /**
@@ -146,14 +153,35 @@ function getWSConnectionHandler(opts) {
146
153
  *
147
154
  * - the context promise will be created immediately on connection if no connectionParams are expected
148
155
  * - if connection params are expected, they will be created once received
149
- */ let ctxPromise = createURL(req).searchParams.get('connectionParams') === '1' ? unsetContextPromiseSymbol : createCtxPromise(()=>null);
150
- async function handleRequest(msg) {
156
+ */ let ctxPromise = createURL(req).searchParams.get('connectionParams') === '1' ? null : createCtxPromise(()=>null);
157
+ function handleRequest(msg) {
151
158
  const { id, jsonrpc } = msg;
152
- /* istanbul ignore next -- @preserve */ if (id === null) {
153
- throw new TRPCError({
154
- code: 'BAD_REQUEST',
159
+ if (id === null) {
160
+ const error = getTRPCErrorFromUnknown(new TRPCError({
161
+ code: 'PARSE_ERROR',
155
162
  message: '`id` is required'
163
+ }));
164
+ opts.onError?.({
165
+ error,
166
+ path: undefined,
167
+ type: 'unknown',
168
+ ctx,
169
+ req,
170
+ input: undefined
156
171
  });
172
+ respond({
173
+ id,
174
+ jsonrpc,
175
+ error: getErrorShape({
176
+ config: router._def._config,
177
+ error,
178
+ type: 'unknown',
179
+ path: undefined,
180
+ input: undefined,
181
+ ctx
182
+ })
183
+ });
184
+ return;
157
185
  }
158
186
  if (msg.method === 'subscription.stop') {
159
187
  clientSubscriptions.get(id)?.abort();
@@ -162,20 +190,24 @@ function getWSConnectionHandler(opts) {
162
190
  const { path, lastEventId } = msg.params;
163
191
  let { input } = msg.params;
164
192
  const type = msg.method;
165
- try {
166
- if (lastEventId !== undefined) {
167
- if (isObject(input)) {
168
- input = {
169
- ...input,
170
- lastEventId: lastEventId
171
- };
172
- } else {
173
- input ?? (input = {
174
- lastEventId: lastEventId
175
- });
176
- }
193
+ if (lastEventId !== undefined) {
194
+ if (isObject(input)) {
195
+ input = {
196
+ ...input,
197
+ lastEventId: lastEventId
198
+ };
199
+ } else {
200
+ input ?? (input = {
201
+ lastEventId: lastEventId
202
+ });
203
+ }
204
+ }
205
+ run(async ()=>{
206
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
207
+ const res = await ctxPromise; // asserts context has been set
208
+ if (!res.ok) {
209
+ throw res.error;
177
210
  }
178
- await ctxPromise; // asserts context has been set
179
211
  const abortController = new AbortController();
180
212
  const result = await callProcedure({
181
213
  router,
@@ -343,7 +375,7 @@ function getWSConnectionHandler(opts) {
343
375
  type: 'started'
344
376
  }
345
377
  });
346
- } catch (cause) /* istanbul ignore next -- @preserve */ {
378
+ }).catch((cause)=>{
347
379
  // procedure threw an error
348
380
  const error = getTRPCErrorFromUnknown(cause);
349
381
  opts.onError?.({
@@ -366,9 +398,9 @@ function getWSConnectionHandler(opts) {
366
398
  ctx
367
399
  })
368
400
  });
369
- }
401
+ });
370
402
  }
371
- client.on('message', async (rawData)=>{
403
+ client.on('message', (rawData)=>{
372
404
  // eslint-disable-next-line @typescript-eslint/no-base-to-string
373
405
  const msgStr = rawData.toString();
374
406
  if (msgStr === 'PONG') {
@@ -380,7 +412,7 @@ function getWSConnectionHandler(opts) {
380
412
  }
381
413
  return;
382
414
  }
383
- if (ctxPromise === unsetContextPromiseSymbol) {
415
+ if (!ctxPromise) {
384
416
  // If the ctxPromise wasn't created immediately, we're expecting the first message to be a TRPCConnectionParamsMessage
385
417
  ctxPromise = createCtxPromise(()=>{
386
418
  let msg;
@@ -401,30 +433,33 @@ function getWSConnectionHandler(opts) {
401
433
  });
402
434
  return;
403
435
  }
404
- try {
405
- const msgJSON = JSON.parse(msgStr);
406
- const msgs = Array.isArray(msgJSON) ? msgJSON : [
407
- msgJSON
408
- ];
409
- const promises = msgs.map((raw)=>parseTRPCMessage(raw, transformer)).map(handleRequest);
410
- await Promise.all(promises);
411
- } catch (cause) {
412
- const error = new TRPCError({
413
- code: 'PARSE_ERROR',
414
- cause
415
- });
416
- respond({
417
- id: null,
418
- error: getErrorShape({
419
- config: router._def._config,
420
- error,
421
- type: 'unknown',
422
- path: undefined,
423
- input: undefined,
424
- ctx: undefined
425
- })
426
- });
427
- }
436
+ const parsedMsgs = run(()=>{
437
+ try {
438
+ const msgJSON = JSON.parse(msgStr);
439
+ const msgs = Array.isArray(msgJSON) ? msgJSON : [
440
+ msgJSON
441
+ ];
442
+ return msgs.map((raw)=>parseTRPCMessage(raw, transformer));
443
+ } catch (cause) {
444
+ const error = new TRPCError({
445
+ code: 'PARSE_ERROR',
446
+ cause
447
+ });
448
+ respond({
449
+ id: null,
450
+ error: getErrorShape({
451
+ config: router._def._config,
452
+ error,
453
+ type: 'unknown',
454
+ path: undefined,
455
+ input: undefined,
456
+ ctx
457
+ })
458
+ });
459
+ return [];
460
+ }
461
+ });
462
+ parsedMsgs.map(handleRequest);
428
463
  });
429
464
  // WebSocket errors should be handled, as otherwise unhandled exceptions will crash Node.js.
430
465
  // This line was introduced after the following error brought down production systems:
@@ -447,9 +482,6 @@ function getWSConnectionHandler(opts) {
447
482
  clientSubscriptions.clear();
448
483
  abortController.abort();
449
484
  });
450
- if (ctxPromise !== unsetContextPromiseSymbol) {
451
- await ctxPromise;
452
- }
453
485
  };
454
486
  }
455
487
  /**
@@ -486,21 +518,7 @@ function applyWSSHandler(opts) {
486
518
  if (opts.prefix && !req.url?.startsWith(opts.prefix)) {
487
519
  return;
488
520
  }
489
- onConnection(client, req).catch((cause)=>{
490
- opts.onError?.({
491
- error: new TRPCError({
492
- code: 'INTERNAL_SERVER_ERROR',
493
- cause,
494
- message: 'Failed to handle WebSocket connection'
495
- }),
496
- req: req,
497
- path: undefined,
498
- type: 'unknown',
499
- ctx: undefined,
500
- input: undefined
501
- });
502
- client.close();
503
- });
521
+ onConnection(client, req);
504
522
  });
505
523
  return {
506
524
  broadcastReconnectNotification: ()=>{