@trpc/server 11.0.0-alpha-tmp-subscription-connection-state.489 → 11.0.0-alpha-tmp-12-06-react.665

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.
Files changed (274) hide show
  1. package/dist/@trpc/server/http.d.ts +1 -1
  2. package/dist/@trpc/server/http.d.ts.map +1 -1
  3. package/dist/@trpc/server/index.d.ts +1 -1
  4. package/dist/@trpc/server/index.d.ts.map +1 -1
  5. package/dist/adapters/aws-lambda/getPlanner.d.ts.map +1 -1
  6. package/dist/adapters/aws-lambda/getPlanner.js +2 -2
  7. package/dist/adapters/aws-lambda/getPlanner.mjs +2 -2
  8. package/dist/adapters/aws-lambda/index.d.ts.map +1 -1
  9. package/dist/adapters/aws-lambda/index.js +2 -0
  10. package/dist/adapters/aws-lambda/index.mjs +2 -0
  11. package/dist/adapters/express.d.ts.map +1 -1
  12. package/dist/adapters/express.js +27 -7
  13. package/dist/adapters/express.mjs +27 -7
  14. package/dist/adapters/fastify/fastifyRequestHandler.js +3 -1
  15. package/dist/adapters/fastify/fastifyRequestHandler.mjs +3 -1
  16. package/dist/adapters/fastify/fastifyTRPCPlugin.d.ts.map +1 -1
  17. package/dist/adapters/fastify/fastifyTRPCPlugin.js +9 -2
  18. package/dist/adapters/fastify/fastifyTRPCPlugin.mjs +10 -3
  19. package/dist/adapters/fetch/fetchRequestHandler.js +9 -8
  20. package/dist/adapters/fetch/fetchRequestHandler.mjs +9 -8
  21. package/dist/adapters/next-app-dir/nextAppDirCaller.d.ts.map +1 -1
  22. package/dist/adapters/next-app-dir/nextAppDirCaller.js +10 -5
  23. package/dist/adapters/next-app-dir/nextAppDirCaller.mjs +10 -5
  24. package/dist/adapters/next-app-dir/notFound.js +2 -0
  25. package/dist/adapters/next-app-dir/notFound.mjs +2 -0
  26. package/dist/adapters/next-app-dir/redirect.js +16 -1
  27. package/dist/adapters/next-app-dir/redirect.mjs +16 -1
  28. package/dist/adapters/next-app-dir/rethrowNextErrors.d.ts.map +1 -1
  29. package/dist/adapters/next-app-dir/rethrowNextErrors.js +4 -3
  30. package/dist/adapters/next-app-dir/rethrowNextErrors.mjs +4 -3
  31. package/dist/adapters/next.d.ts.map +1 -1
  32. package/dist/adapters/next.js +23 -30
  33. package/dist/adapters/next.mjs +24 -31
  34. package/dist/adapters/node-http/incomingMessageToRequest.d.ts +2 -1
  35. package/dist/adapters/node-http/incomingMessageToRequest.d.ts.map +1 -1
  36. package/dist/adapters/node-http/incomingMessageToRequest.js +83 -40
  37. package/dist/adapters/node-http/incomingMessageToRequest.mjs +83 -41
  38. package/dist/adapters/node-http/index.js +2 -0
  39. package/dist/adapters/node-http/index.mjs +2 -2
  40. package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts +7 -0
  41. package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
  42. package/dist/adapters/node-http/nodeHTTPRequestHandler.js +70 -58
  43. package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +70 -59
  44. package/dist/adapters/node-http/writeResponse.d.ts +18 -0
  45. package/dist/adapters/node-http/writeResponse.d.ts.map +1 -0
  46. package/dist/adapters/node-http/writeResponse.js +82 -0
  47. package/dist/adapters/node-http/writeResponse.mjs +79 -0
  48. package/dist/adapters/standalone.d.ts +5 -2
  49. package/dist/adapters/standalone.d.ts.map +1 -1
  50. package/dist/adapters/standalone.js +25 -13
  51. package/dist/adapters/standalone.mjs +26 -14
  52. package/dist/adapters/ws.d.ts +14 -4
  53. package/dist/adapters/ws.d.ts.map +1 -1
  54. package/dist/adapters/ws.js +217 -101
  55. package/dist/adapters/ws.mjs +217 -102
  56. package/dist/bundle-analysis.json +412 -310
  57. package/dist/http.js +2 -4
  58. package/dist/http.mjs +2 -2
  59. package/dist/index.js +3 -0
  60. package/dist/index.mjs +3 -1
  61. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.1_rollup@4.27.4_tslib@2.8.1_typescript@5.7.2/node_modules/tslib/tslib.es6.js +73 -0
  62. package/dist/observable/behaviorSubject.d.ts +15 -0
  63. package/dist/observable/behaviorSubject.d.ts.map +1 -0
  64. package/dist/observable/behaviorSubject.js +40 -0
  65. package/dist/observable/behaviorSubject.mjs +38 -0
  66. package/dist/observable/index.d.ts +3 -3
  67. package/dist/observable/index.d.ts.map +1 -1
  68. package/dist/observable/index.js +5 -0
  69. package/dist/observable/index.mjs +3 -2
  70. package/dist/observable/observable.d.ts +2 -1
  71. package/dist/observable/observable.d.ts.map +1 -1
  72. package/dist/observable/observable.js +31 -8
  73. package/dist/observable/observable.mjs +31 -8
  74. package/dist/observable/operators.d.ts +2 -0
  75. package/dist/observable/operators.d.ts.map +1 -1
  76. package/dist/observable/operators.js +35 -0
  77. package/dist/observable/operators.mjs +34 -1
  78. package/dist/rpc.js +2 -0
  79. package/dist/rpc.mjs +2 -0
  80. package/dist/shared.js +2 -0
  81. package/dist/shared.mjs +2 -0
  82. package/dist/unstable-core-do-not-import/clientish/inference.d.ts.map +1 -1
  83. package/dist/unstable-core-do-not-import/clientish/inferrable.d.ts.map +1 -1
  84. package/dist/unstable-core-do-not-import/clientish/serialize.d.ts +2 -2
  85. package/dist/unstable-core-do-not-import/clientish/serialize.d.ts.map +1 -1
  86. package/dist/unstable-core-do-not-import/createProxy.js +1 -1
  87. package/dist/unstable-core-do-not-import/createProxy.mjs +1 -1
  88. package/dist/unstable-core-do-not-import/error/TRPCError.d.ts +1 -1
  89. package/dist/unstable-core-do-not-import/error/TRPCError.js +16 -1
  90. package/dist/unstable-core-do-not-import/error/TRPCError.mjs +16 -1
  91. package/dist/unstable-core-do-not-import/error/formatter.js +1 -1
  92. package/dist/unstable-core-do-not-import/error/formatter.mjs +1 -1
  93. package/dist/unstable-core-do-not-import/error/getErrorShape.js +2 -2
  94. package/dist/unstable-core-do-not-import/error/getErrorShape.mjs +2 -2
  95. package/dist/unstable-core-do-not-import/http/contentType.js +3 -3
  96. package/dist/unstable-core-do-not-import/http/contentType.mjs +3 -3
  97. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.d.ts +6 -1
  98. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.d.ts.map +1 -1
  99. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.js +28 -0
  100. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.mjs +25 -1
  101. package/dist/unstable-core-do-not-import/http/isAbortError.d.ts +4 -0
  102. package/dist/unstable-core-do-not-import/http/isAbortError.d.ts.map +1 -0
  103. package/dist/unstable-core-do-not-import/http/isAbortError.js +9 -0
  104. package/dist/unstable-core-do-not-import/http/isAbortError.mjs +7 -0
  105. package/dist/unstable-core-do-not-import/http/resolveResponse.d.ts.map +1 -1
  106. package/dist/unstable-core-do-not-import/http/resolveResponse.js +180 -96
  107. package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +182 -98
  108. package/dist/unstable-core-do-not-import/http/types.d.ts +1 -1
  109. package/dist/unstable-core-do-not-import/initTRPC.d.ts +11 -11
  110. package/dist/unstable-core-do-not-import/initTRPC.d.ts.map +1 -1
  111. package/dist/unstable-core-do-not-import/initTRPC.js +11 -11
  112. package/dist/unstable-core-do-not-import/initTRPC.mjs +11 -11
  113. package/dist/unstable-core-do-not-import/middleware.d.ts +2 -1
  114. package/dist/unstable-core-do-not-import/middleware.d.ts.map +1 -1
  115. package/dist/unstable-core-do-not-import/middleware.js +2 -2
  116. package/dist/unstable-core-do-not-import/middleware.mjs +2 -2
  117. package/dist/unstable-core-do-not-import/parser.d.ts +5 -1
  118. package/dist/unstable-core-do-not-import/parser.d.ts.map +1 -1
  119. package/dist/unstable-core-do-not-import/parser.js +4 -0
  120. package/dist/unstable-core-do-not-import/parser.mjs +4 -0
  121. package/dist/unstable-core-do-not-import/procedure.d.ts +8 -2
  122. package/dist/unstable-core-do-not-import/procedure.d.ts.map +1 -1
  123. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +31 -12
  124. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
  125. package/dist/unstable-core-do-not-import/procedureBuilder.js +33 -39
  126. package/dist/unstable-core-do-not-import/procedureBuilder.mjs +33 -39
  127. package/dist/unstable-core-do-not-import/rootConfig.d.ts +17 -17
  128. package/dist/unstable-core-do-not-import/rootConfig.d.ts.map +1 -1
  129. package/dist/unstable-core-do-not-import/router.d.ts +4 -3
  130. package/dist/unstable-core-do-not-import/router.d.ts.map +1 -1
  131. package/dist/unstable-core-do-not-import/router.js +6 -5
  132. package/dist/unstable-core-do-not-import/router.mjs +6 -5
  133. package/dist/unstable-core-do-not-import/rpc/codes.d.ts +2 -9
  134. package/dist/unstable-core-do-not-import/rpc/codes.d.ts.map +1 -1
  135. package/dist/unstable-core-do-not-import/rpc/envelopes.d.ts +7 -10
  136. package/dist/unstable-core-do-not-import/rpc/envelopes.d.ts.map +1 -1
  137. package/dist/unstable-core-do-not-import/rpc/parseTRPCMessage.js +2 -2
  138. package/dist/unstable-core-do-not-import/rpc/parseTRPCMessage.mjs +2 -2
  139. package/dist/unstable-core-do-not-import/stream/jsonl.d.ts +25 -14
  140. package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -1
  141. package/dist/unstable-core-do-not-import/stream/jsonl.js +439 -318
  142. package/dist/unstable-core-do-not-import/stream/jsonl.mjs +439 -318
  143. package/dist/unstable-core-do-not-import/stream/sse.d.ts +58 -18
  144. package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
  145. package/dist/unstable-core-do-not-import/stream/sse.js +297 -122
  146. package/dist/unstable-core-do-not-import/stream/sse.mjs +298 -123
  147. package/dist/unstable-core-do-not-import/stream/sse.types.d.ts +31 -0
  148. package/dist/unstable-core-do-not-import/stream/sse.types.d.ts.map +1 -0
  149. package/dist/unstable-core-do-not-import/stream/tracked.d.ts +2 -2
  150. package/dist/unstable-core-do-not-import/stream/tracked.d.ts.map +1 -1
  151. package/dist/unstable-core-do-not-import/stream/tracked.js +1 -1
  152. package/dist/unstable-core-do-not-import/stream/tracked.mjs +1 -1
  153. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts +17 -0
  154. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts.map +1 -0
  155. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.js +171 -0
  156. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.mjs +167 -0
  157. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts +0 -11
  158. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts.map +1 -1
  159. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.js +0 -29
  160. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.mjs +1 -29
  161. package/dist/unstable-core-do-not-import/stream/utils/disposable.d.ts +17 -0
  162. package/dist/unstable-core-do-not-import/stream/utils/disposable.d.ts.map +1 -0
  163. package/dist/unstable-core-do-not-import/stream/utils/disposable.js +44 -0
  164. package/dist/unstable-core-do-not-import/stream/utils/disposable.mjs +41 -0
  165. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.d.ts +8 -0
  166. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.d.ts.map +1 -0
  167. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.js +25 -0
  168. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.mjs +23 -0
  169. package/dist/unstable-core-do-not-import/stream/utils/timerResource.d.ts +5 -0
  170. package/dist/unstable-core-do-not-import/stream/utils/timerResource.d.ts.map +1 -0
  171. package/dist/unstable-core-do-not-import/stream/utils/timerResource.js +26 -0
  172. package/dist/unstable-core-do-not-import/stream/utils/timerResource.mjs +23 -0
  173. package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts +7 -0
  174. package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts.map +1 -0
  175. package/dist/unstable-core-do-not-import/stream/utils/withPing.js +130 -0
  176. package/dist/unstable-core-do-not-import/stream/utils/withPing.mjs +127 -0
  177. package/dist/unstable-core-do-not-import/transformer.d.ts +2 -5
  178. package/dist/unstable-core-do-not-import/transformer.d.ts.map +1 -1
  179. package/dist/unstable-core-do-not-import/transformer.js +1 -1
  180. package/dist/unstable-core-do-not-import/transformer.mjs +1 -1
  181. package/dist/unstable-core-do-not-import/types.d.ts +26 -3
  182. package/dist/unstable-core-do-not-import/types.d.ts.map +1 -1
  183. package/dist/unstable-core-do-not-import/utils.d.ts +15 -0
  184. package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
  185. package/dist/unstable-core-do-not-import/utils.js +49 -1
  186. package/dist/unstable-core-do-not-import/utils.mjs +45 -2
  187. package/dist/unstable-core-do-not-import.d.ts +3 -2
  188. package/dist/unstable-core-do-not-import.d.ts.map +1 -1
  189. package/dist/unstable-core-do-not-import.js +14 -7
  190. package/dist/unstable-core-do-not-import.mjs +5 -6
  191. package/dist/vendor/unpromise/index.d.ts +3 -0
  192. package/dist/vendor/unpromise/index.d.ts.map +1 -0
  193. package/dist/vendor/unpromise/types.d.ts +28 -0
  194. package/dist/vendor/unpromise/types.d.ts.map +1 -0
  195. package/dist/vendor/unpromise/unpromise.d.ts +121 -0
  196. package/dist/vendor/unpromise/unpromise.d.ts.map +1 -0
  197. package/dist/vendor/unpromise/unpromise.js +292 -0
  198. package/dist/vendor/unpromise/unpromise.mjs +289 -0
  199. package/package.json +20 -17
  200. package/src/@trpc/server/http.ts +0 -2
  201. package/src/@trpc/server/index.ts +2 -0
  202. package/src/adapters/aws-lambda/getPlanner.ts +2 -2
  203. package/src/adapters/aws-lambda/index.ts +5 -6
  204. package/src/adapters/express.ts +21 -9
  205. package/src/adapters/fastify/fastifyRequestHandler.ts +1 -1
  206. package/src/adapters/fastify/fastifyTRPCPlugin.ts +16 -5
  207. package/src/adapters/fetch/fetchRequestHandler.ts +2 -2
  208. package/src/adapters/next-app-dir/nextAppDirCaller.ts +3 -0
  209. package/src/adapters/next-app-dir/rethrowNextErrors.ts +3 -2
  210. package/src/adapters/next.ts +29 -34
  211. package/src/adapters/node-http/incomingMessageToRequest.ts +110 -40
  212. package/src/adapters/node-http/nodeHTTPRequestHandler.ts +85 -63
  213. package/src/adapters/node-http/writeResponse.ts +94 -0
  214. package/src/adapters/standalone.ts +35 -18
  215. package/src/adapters/ws.ts +111 -57
  216. package/src/observable/behaviorSubject.ts +55 -0
  217. package/src/observable/index.ts +22 -3
  218. package/src/observable/observable.ts +32 -14
  219. package/src/observable/operators.ts +47 -0
  220. package/src/unstable-core-do-not-import/clientish/inference.ts +4 -4
  221. package/src/unstable-core-do-not-import/clientish/inferrable.ts +6 -6
  222. package/src/unstable-core-do-not-import/clientish/serialize.ts +5 -5
  223. package/src/unstable-core-do-not-import/http/getHTTPStatusCode.ts +37 -4
  224. package/src/unstable-core-do-not-import/http/isAbortError.ts +7 -0
  225. package/src/unstable-core-do-not-import/http/resolveResponse.ts +185 -90
  226. package/src/unstable-core-do-not-import/http/types.ts +1 -1
  227. package/src/unstable-core-do-not-import/initTRPC.ts +14 -20
  228. package/src/unstable-core-do-not-import/middleware.ts +5 -4
  229. package/src/unstable-core-do-not-import/parser.ts +17 -6
  230. package/src/unstable-core-do-not-import/procedure.ts +17 -2
  231. package/src/unstable-core-do-not-import/procedureBuilder.ts +137 -122
  232. package/src/unstable-core-do-not-import/rootConfig.ts +20 -20
  233. package/src/unstable-core-do-not-import/router.ts +15 -16
  234. package/src/unstable-core-do-not-import/rpc/codes.ts +2 -10
  235. package/src/unstable-core-do-not-import/rpc/envelopes.ts +7 -12
  236. package/src/unstable-core-do-not-import/stream/jsonl.ts +287 -296
  237. package/src/unstable-core-do-not-import/stream/sse.ts +338 -171
  238. package/src/unstable-core-do-not-import/stream/sse.types.ts +44 -0
  239. package/src/unstable-core-do-not-import/stream/tracked.ts +5 -11
  240. package/src/unstable-core-do-not-import/stream/utils/asyncIterable.ts +89 -0
  241. package/src/unstable-core-do-not-import/stream/utils/createDeferred.ts +0 -36
  242. package/src/unstable-core-do-not-import/stream/utils/disposable.ts +52 -0
  243. package/src/unstable-core-do-not-import/stream/utils/readableStreamFrom.ts +28 -0
  244. package/src/unstable-core-do-not-import/stream/utils/timerResource.ts +29 -0
  245. package/src/unstable-core-do-not-import/stream/utils/withPing.ts +47 -0
  246. package/src/unstable-core-do-not-import/transformer.ts +1 -1
  247. package/src/unstable-core-do-not-import/types.ts +35 -10
  248. package/src/unstable-core-do-not-import/utils.ts +56 -1
  249. package/src/unstable-core-do-not-import.ts +3 -2
  250. package/src/vendor/unpromise/ATTRIBUTION.txt +1 -0
  251. package/src/vendor/unpromise/LICENSE +20 -0
  252. package/src/vendor/unpromise/index.ts +7 -0
  253. package/src/vendor/unpromise/types.ts +55 -0
  254. package/src/vendor/unpromise/unpromise.ts +380 -0
  255. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.d.ts +0 -24
  256. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.d.ts.map +0 -1
  257. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.js +0 -32
  258. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.mjs +0 -30
  259. package/dist/unstable-core-do-not-import/http/toURL.d.ts +0 -2
  260. package/dist/unstable-core-do-not-import/http/toURL.d.ts.map +0 -1
  261. package/dist/unstable-core-do-not-import/http/toURL.js +0 -8
  262. package/dist/unstable-core-do-not-import/http/toURL.mjs +0 -6
  263. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts +0 -10
  264. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts.map +0 -1
  265. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.js +0 -31
  266. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.mjs +0 -29
  267. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts +0 -7
  268. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts.map +0 -1
  269. package/dist/unstable-core-do-not-import/types.js +0 -11
  270. package/dist/unstable-core-do-not-import/types.mjs +0 -9
  271. package/src/unstable-core-do-not-import/http/batchStreamFormatter.ts +0 -29
  272. package/src/unstable-core-do-not-import/http/toURL.ts +0 -7
  273. package/src/unstable-core-do-not-import/stream/utils/createReadableStream.ts +0 -31
  274. package/src/unstable-core-do-not-import/stream/utils/createServer.ts +0 -44
@@ -13,7 +13,7 @@ import {
13
13
  TRPCError,
14
14
  } from '../@trpc/server';
15
15
  import type { TRPCRequestInfo } from '../@trpc/server/http';
16
- import { toURL, type BaseHandlerOptions } from '../@trpc/server/http';
16
+ import { type BaseHandlerOptions } from '../@trpc/server/http';
17
17
  import { parseTRPCMessage } from '../@trpc/server/rpc';
18
18
  // @trpc/server/rpc
19
19
  import type {
@@ -24,8 +24,7 @@ import type {
24
24
  TRPCResultMessage,
25
25
  } from '../@trpc/server/rpc';
26
26
  import { parseConnectionParamsFromUnknown } from '../http';
27
- import { isObservable } from '../observable';
28
- import { observableToAsyncIterable } from '../observable/observable';
27
+ import { isObservable, observableToAsyncIterable } from '../observable';
29
28
  // eslint-disable-next-line no-restricted-imports
30
29
  import {
31
30
  isAsyncIterable,
@@ -34,11 +33,14 @@ import {
34
33
  run,
35
34
  type MaybePromise,
36
35
  } from '../unstable-core-do-not-import';
37
- import type { NodeHTTPCreateContextFnOptions } from './node-http';
36
+ // eslint-disable-next-line no-restricted-imports
37
+ import { iteratorResource } from '../unstable-core-do-not-import/stream/utils/asyncIterable';
38
+ import { Unpromise } from '../vendor/unpromise';
39
+ import { createURL, type NodeHTTPCreateContextFnOptions } from './node-http';
38
40
 
39
41
  /**
40
42
  * Importing ws causes a build error
41
- * @link https://github.com/trpc/trpc/pull/5279
43
+ * @see https://github.com/trpc/trpc/pull/5279
42
44
  */
43
45
  const WEBSOCKET_OPEN = 1; /* ws.WebSocket.OPEN */
44
46
 
@@ -79,20 +81,26 @@ export type WSSHandlerOptions<TRouter extends AnyRouter> =
79
81
  enabled: boolean;
80
82
  /**
81
83
  * Heartbeat interval in milliseconds
82
- * @default 30000
84
+ * @default 30_000
83
85
  */
84
86
  pingMs?: number;
85
87
  /**
86
88
  * Terminate the WebSocket if no pong is received after this many milliseconds
87
- * @default 5000
89
+ * @default 5_000
88
90
  */
89
91
  pongWaitMs?: number;
90
92
  };
93
+ /**
94
+ * Disable responding to ping messages from the client
95
+ * **Not recommended** - this is mainly used for testing
96
+ * @default false
97
+ */
98
+ dangerouslyDisablePong?: boolean;
91
99
  };
92
100
 
93
101
  const unsetContextPromiseSymbol = Symbol('unsetContextPromise');
94
102
  export function getWSConnectionHandler<TRouter extends AnyRouter>(
95
- opts: WSConnectionHandlerOptions<TRouter>,
103
+ opts: WSSHandlerOptions<TRouter>,
96
104
  ) {
97
105
  const { createContext, router } = opts;
98
106
  const { transformer } = router._def._config;
@@ -101,6 +109,11 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
101
109
  const clientSubscriptions = new Map<number | string, AbortController>();
102
110
  const abortController = new AbortController();
103
111
 
112
+ if (opts.keepAlive?.enabled) {
113
+ const { pingMs, pongWaitMs } = opts.keepAlive;
114
+ handleKeepAlive(client, pingMs, pongWaitMs);
115
+ }
116
+
104
117
  function respond(untransformedJSON: TRPCResponseMessage) {
105
118
  client.send(
106
119
  JSON.stringify(
@@ -167,7 +180,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
167
180
  * - if connection params are expected, they will be created once received
168
181
  */
169
182
  let ctxPromise =
170
- toURL(req.url ?? '').searchParams.get('connectionParams') === '1'
183
+ createURL(req).searchParams.get('connectionParams') === '1'
171
184
  ? unsetContextPromiseSymbol
172
185
  : createCtxPromise(() => null);
173
186
 
@@ -203,12 +216,14 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
203
216
  }
204
217
  await ctxPromise; // asserts context has been set
205
218
 
219
+ const abortController = new AbortController();
206
220
  const result = await callProcedure({
207
221
  procedures: router._def.procedures,
208
222
  path,
209
223
  getRawInput: async () => input,
210
224
  ctx,
211
225
  type,
226
+ signal: abortController.signal,
212
227
  });
213
228
 
214
229
  const isIterableResult =
@@ -259,20 +274,27 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
259
274
  }
260
275
 
261
276
  const iterable = isObservable(result)
262
- ? observableToAsyncIterable(result)
277
+ ? observableToAsyncIterable(result, abortController.signal)
263
278
  : result;
264
279
 
265
- const iterator: AsyncIterator<unknown> =
266
- iterable[Symbol.asyncIterator]();
267
- const abortController = new AbortController();
280
+ run(async () => {
281
+ await using iterator = iteratorResource(iterable);
268
282
 
269
- const abortPromise = new Promise<'abort'>((resolve) => {
270
- abortController.signal.onabort = () => resolve('abort');
271
- });
283
+ const abortPromise = new Promise<'abort'>((resolve) => {
284
+ abortController.signal.onabort = () => resolve('abort');
285
+ });
286
+ // We need those declarations outside the loop for garbage collection reasons. If they
287
+ // were declared inside, they would not be freed until the next value is present.
288
+ let next:
289
+ | null
290
+ | TRPCError
291
+ | Awaited<
292
+ typeof abortPromise | ReturnType<(typeof iterator)['next']>
293
+ >;
294
+ let result: null | TRPCResultMessage<unknown>['result'];
272
295
 
273
- run(async () => {
274
296
  while (true) {
275
- const next = await Promise.race([
297
+ next = await Unpromise.race([
276
298
  iterator.next().catch(getTRPCErrorFromUnknown),
277
299
  abortPromise,
278
300
  ]);
@@ -302,7 +324,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
302
324
  break;
303
325
  }
304
326
 
305
- const result: TRPCResultMessage<unknown>['result'] = {
327
+ result = {
306
328
  type: 'data',
307
329
  data: next.value,
308
330
  };
@@ -321,9 +343,12 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
321
343
  jsonrpc,
322
344
  result,
323
345
  });
346
+
347
+ // free up references for garbage collection
348
+ next = null;
349
+ result = null;
324
350
  }
325
351
 
326
- await iterator.return?.();
327
352
  respond({
328
353
  id,
329
354
  jsonrpc,
@@ -376,13 +401,24 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
376
401
  });
377
402
  }
378
403
  }
379
- client.on('message', async (message) => {
404
+ client.on('message', async (rawData) => {
405
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
406
+ const msgStr = rawData.toString();
407
+ if (msgStr === 'PONG') {
408
+ return;
409
+ }
410
+ if (msgStr === 'PING') {
411
+ if (!opts.dangerouslyDisablePong) {
412
+ client.send('PONG');
413
+ }
414
+ return;
415
+ }
380
416
  if (ctxPromise === unsetContextPromiseSymbol) {
381
417
  // If the ctxPromise wasn't created immediately, we're expecting the first message to be a TRPCConnectionParamsMessage
382
418
  ctxPromise = createCtxPromise(() => {
383
419
  let msg;
384
420
  try {
385
- msg = JSON.parse(message.toString()) as TRPCConnectionParamsMessage;
421
+ msg = JSON.parse(msgStr) as TRPCConnectionParamsMessage;
386
422
 
387
423
  if (!isObject(msg)) {
388
424
  throw new Error('Message was not an object');
@@ -402,7 +438,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
402
438
  return;
403
439
  }
404
440
  try {
405
- const msgJSON: unknown = JSON.parse(message.toString());
441
+ const msgJSON: unknown = JSON.parse(msgStr);
406
442
  const msgs: unknown[] = Array.isArray(msgJSON) ? msgJSON : [msgJSON];
407
443
  const promises = msgs
408
444
  .map((raw) => parseTRPCMessage(raw, transformer))
@@ -452,8 +488,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
452
488
  });
453
489
 
454
490
  if (ctxPromise !== unsetContextPromiseSymbol) {
455
- // prevent unhandled promise rejection errors
456
- await ctxPromise.catch(() => null);
491
+ await ctxPromise;
457
492
  }
458
493
  };
459
494
  }
@@ -461,50 +496,69 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
461
496
  /**
462
497
  * Handle WebSocket keep-alive messages
463
498
  */
464
- function handleKeepAlive(
499
+ export function handleKeepAlive(
465
500
  client: ws.WebSocket,
466
- pingMs = 30000,
467
- pongWaitMs = 5000,
501
+ pingMs = 30_000,
502
+ pongWaitMs = 5_000,
468
503
  ) {
469
- let heartbeatTimeout: NodeJS.Timeout | undefined;
470
- const heartbeatInterval = setInterval(() => {
471
- if (client.readyState !== WEBSOCKET_OPEN) {
472
- return;
473
- }
474
- // First we send a ping message and wait for a pong
475
- client.ping();
476
- // We set a timeout to close the connection if the pong is not received
477
- heartbeatTimeout = setTimeout(() => {
478
- client.terminate();
479
- clearInterval(heartbeatInterval);
480
- }, pongWaitMs);
481
- }, pingMs).unref();
482
- // When we receive a pong message, we clear the timeout
483
- client.on('pong', () => {
484
- heartbeatTimeout && clearTimeout(heartbeatTimeout);
485
- });
486
- // If the connection is closed, we clear the interval
504
+ let timeout: NodeJS.Timeout | undefined = undefined;
505
+ let ping: NodeJS.Timeout | undefined = undefined;
506
+
507
+ const schedulePing = () => {
508
+ const scheduleTimeout = () => {
509
+ timeout = setTimeout(() => {
510
+ client.terminate();
511
+ }, pongWaitMs);
512
+ };
513
+ ping = setTimeout(() => {
514
+ client.send('PING');
515
+
516
+ scheduleTimeout();
517
+ }, pingMs);
518
+ };
519
+
520
+ const onMessage = () => {
521
+ clearTimeout(ping);
522
+ clearTimeout(timeout);
523
+
524
+ schedulePing();
525
+ };
526
+
527
+ client.on('message', onMessage);
528
+
487
529
  client.on('close', () => {
488
- clearInterval(heartbeatInterval);
530
+ clearTimeout(ping);
531
+ clearTimeout(timeout);
489
532
  });
533
+
534
+ schedulePing();
490
535
  }
491
536
 
492
537
  export function applyWSSHandler<TRouter extends AnyRouter>(
493
538
  opts: WSSHandlerOptions<TRouter>,
494
539
  ) {
495
- const { wss, prefix, keepAlive } = opts;
496
-
497
540
  const onConnection = getWSConnectionHandler(opts);
498
- wss.on('connection', async (client, req) => {
499
- if (prefix && !req.url?.startsWith(prefix)) {
541
+ opts.wss.on('connection', (client, req) => {
542
+ if (opts.prefix && !req.url?.startsWith(opts.prefix)) {
500
543
  return;
501
544
  }
502
545
 
503
- await onConnection(client, req);
504
- if (keepAlive?.enabled) {
505
- const { pingMs, pongWaitMs } = keepAlive;
506
- handleKeepAlive(client, pingMs, pongWaitMs);
507
- }
546
+ onConnection(client, req).catch((cause) => {
547
+ opts.onError?.({
548
+ error: new TRPCError({
549
+ code: 'INTERNAL_SERVER_ERROR',
550
+ cause,
551
+ message: 'Failed to handle WebSocket connection',
552
+ }),
553
+ req: req,
554
+ path: undefined,
555
+ type: 'unknown',
556
+ ctx: undefined,
557
+ input: undefined,
558
+ });
559
+
560
+ client.close();
561
+ });
508
562
  });
509
563
 
510
564
  return {
@@ -514,7 +568,7 @@ export function applyWSSHandler<TRouter extends AnyRouter>(
514
568
  method: 'reconnect',
515
569
  };
516
570
  const data = JSON.stringify(response);
517
- for (const client of wss.clients) {
571
+ for (const client of opts.wss.clients) {
518
572
  if (client.readyState === WEBSOCKET_OPEN) {
519
573
  client.send(data);
520
574
  }
@@ -0,0 +1,55 @@
1
+ import { observable } from './observable';
2
+ import type { Observable, Observer } from './types';
3
+
4
+ export interface BehaviorSubject<TValue> extends Observable<TValue, never> {
5
+ observable: Observable<TValue, never>;
6
+ next: (value: TValue) => void;
7
+ get: () => TValue;
8
+ }
9
+
10
+ export interface ReadonlyBehaviorSubject<TValue>
11
+ extends Omit<BehaviorSubject<TValue>, 'next'> {}
12
+
13
+ /**
14
+ * @internal
15
+ * An observable that maintains and provides a "current value" to subscribers
16
+ * @see https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject
17
+ */
18
+ export function behaviorSubject<TValue>(
19
+ initialValue: TValue,
20
+ ): BehaviorSubject<TValue> {
21
+ let value: TValue = initialValue;
22
+
23
+ const observerList: Observer<TValue, never>[] = [];
24
+
25
+ const addObserver = (observer: Observer<TValue, never>) => {
26
+ if (value !== undefined) {
27
+ observer.next(value);
28
+ }
29
+ observerList.push(observer);
30
+ };
31
+ const removeObserver = (observer: Observer<TValue, never>) => {
32
+ observerList.splice(observerList.indexOf(observer), 1);
33
+ };
34
+
35
+ const obs = observable<TValue, never>((observer) => {
36
+ addObserver(observer);
37
+ return () => {
38
+ removeObserver(observer);
39
+ };
40
+ }) as BehaviorSubject<TValue>;
41
+
42
+ obs.next = (nextValue: TValue) => {
43
+ if (value === nextValue) {
44
+ return;
45
+ }
46
+ value = nextValue;
47
+ for (const observer of observerList) {
48
+ observer.next(nextValue);
49
+ }
50
+ };
51
+
52
+ obs.get = () => value;
53
+
54
+ return obs;
55
+ }
@@ -1,6 +1,19 @@
1
- export type { inferObservableValue } from './observable';
2
- export { isObservable, observable, observableToPromise } from './observable';
3
- export { map, share, tap } from './operators';
1
+ export {
2
+ isObservable,
3
+ observable,
4
+ observableToAsyncIterable,
5
+ observableToPromise,
6
+ type inferObservableValue,
7
+ } from './observable';
8
+
9
+ export {
10
+ distinctUntilChanged,
11
+ distinctUntilDeepChanged,
12
+ map,
13
+ share,
14
+ tap,
15
+ } from './operators';
16
+
4
17
  export type {
5
18
  Observable,
6
19
  Observer,
@@ -8,3 +21,9 @@ export type {
8
21
  Unsubscribable,
9
22
  UnsubscribeFn,
10
23
  } from './types';
24
+
25
+ export {
26
+ behaviorSubject,
27
+ type BehaviorSubject,
28
+ type ReadonlyBehaviorSubject,
29
+ } from './behaviorSubject';
@@ -1,3 +1,4 @@
1
+ import type { Result } from '../unstable-core-do-not-import';
1
2
  import type {
2
3
  Observable,
3
4
  Observer,
@@ -8,12 +9,8 @@ import type {
8
9
  } from './types';
9
10
 
10
11
  /** @public */
11
- export type inferObservableValue<TObservable> = TObservable extends Observable<
12
- infer TValue,
13
- unknown
14
- >
15
- ? TValue
16
- : never;
12
+ export type inferObservableValue<TObservable> =
13
+ TObservable extends Observable<infer TValue, unknown> ? TValue : never;
17
14
 
18
15
  /** @public */
19
16
  export function isObservable(x: unknown): x is Observable<unknown, unknown> {
@@ -130,32 +127,49 @@ export function observableToPromise<TValue>(
130
127
  */
131
128
  function observableToReadableStream<TValue>(
132
129
  observable: Observable<TValue, unknown>,
133
- ): ReadableStream<TValue> {
130
+ signal: AbortSignal,
131
+ ): ReadableStream<Result<TValue>> {
134
132
  let unsub: Unsubscribable | null = null;
135
- return new ReadableStream<TValue>({
133
+
134
+ const onAbort = () => {
135
+ unsub?.unsubscribe();
136
+ unsub = null;
137
+ signal.removeEventListener('abort', onAbort);
138
+ };
139
+
140
+ return new ReadableStream<Result<TValue>>({
136
141
  start(controller) {
137
142
  unsub = observable.subscribe({
138
143
  next(data) {
139
- controller.enqueue(data);
144
+ controller.enqueue({ ok: true, value: data });
140
145
  },
141
- error(err) {
142
- controller.error(err);
146
+ error(error) {
147
+ controller.enqueue({ ok: false, error });
148
+ controller.close();
143
149
  },
144
150
  complete() {
145
151
  controller.close();
146
152
  },
147
153
  });
154
+
155
+ if (signal.aborted) {
156
+ onAbort();
157
+ } else {
158
+ signal.addEventListener('abort', onAbort, { once: true });
159
+ }
148
160
  },
149
161
  cancel() {
150
- unsub?.unsubscribe();
162
+ onAbort();
151
163
  },
152
164
  });
153
165
  }
154
166
 
167
+ /** @internal */
155
168
  export function observableToAsyncIterable<TValue>(
156
169
  observable: Observable<TValue, unknown>,
170
+ signal: AbortSignal,
157
171
  ): AsyncIterable<TValue> {
158
- const stream = observableToReadableStream(observable);
172
+ const stream = observableToReadableStream(observable, signal);
159
173
 
160
174
  const reader = stream.getReader();
161
175
  const iterator: AsyncIterator<TValue> = {
@@ -167,8 +181,12 @@ export function observableToAsyncIterable<TValue>(
167
181
  done: true,
168
182
  };
169
183
  }
184
+ const { value: result } = value;
185
+ if (!result.ok) {
186
+ throw result.error;
187
+ }
170
188
  return {
171
- value: value.value,
189
+ value: result.value,
172
190
  done: false,
173
191
  };
174
192
  },
@@ -112,3 +112,50 @@ export function tap<TValue, TError>(
112
112
  });
113
113
  };
114
114
  }
115
+
116
+ const distinctUnsetMarker = Symbol();
117
+ export function distinctUntilChanged<TValue, TError>(
118
+ compare: (a: TValue, b: TValue) => boolean = (a, b) => a === b,
119
+ ): MonoTypeOperatorFunction<TValue, TError> {
120
+ return (source) => {
121
+ return observable((destination) => {
122
+ let lastValue: TValue | typeof distinctUnsetMarker = distinctUnsetMarker;
123
+
124
+ return source.subscribe({
125
+ next(value) {
126
+ if (lastValue !== distinctUnsetMarker && compare(lastValue, value)) {
127
+ return;
128
+ }
129
+ lastValue = value;
130
+ destination.next(value);
131
+ },
132
+ error(error) {
133
+ destination.error(error);
134
+ },
135
+ complete() {
136
+ destination.complete();
137
+ },
138
+ });
139
+ });
140
+ };
141
+ }
142
+
143
+ const isDeepEqual = <T>(a: T, b: T): boolean => {
144
+ if (a === b) {
145
+ return true;
146
+ }
147
+ const bothAreObjects =
148
+ a && b && typeof a === 'object' && typeof b === 'object';
149
+
150
+ return (
151
+ !!bothAreObjects &&
152
+ Object.keys(a).length === Object.keys(b).length &&
153
+ Object.entries(a).every(([k, v]) => isDeepEqual(v, b[k as keyof T]))
154
+ );
155
+ };
156
+ export function distinctUntilDeepChanged<
157
+ TValue,
158
+ TError,
159
+ >(): MonoTypeOperatorFunction<TValue, TError> {
160
+ return distinctUntilChanged(isDeepEqual);
161
+ }
@@ -40,10 +40,10 @@ export type GetInferenceHelpers<
40
40
  ? $Value extends RouterRecord
41
41
  ? GetInferenceHelpers<TType, TRoot, $Value>
42
42
  : $Value extends AnyProcedure
43
- ? TType extends 'input'
44
- ? inferProcedureInput<$Value>
45
- : inferTransformedProcedureOutput<TRoot, $Value>
46
- : never
43
+ ? TType extends 'input'
44
+ ? inferProcedureInput<$Value>
45
+ : inferTransformedProcedureOutput<TRoot, $Value>
46
+ : never
47
47
  : never;
48
48
  };
49
49
 
@@ -41,9 +41,9 @@ export type inferClientTypes<TInferrable extends InferrableClientTypes> =
41
41
  TInferrable extends AnyClientTypes
42
42
  ? TInferrable
43
43
  : TInferrable extends RootConfigLike
44
- ? TInferrable['$types']
45
- : TInferrable extends InitLike
46
- ? TInferrable['_config']['$types']
47
- : TInferrable extends RouterLike
48
- ? TInferrable['_def']['_config']['$types']
49
- : never;
44
+ ? TInferrable['$types']
45
+ : TInferrable extends InitLike
46
+ ? TInferrable['_config']['$types']
47
+ : TInferrable extends RouterLike
48
+ ? TInferrable['_def']['_config']['$types']
49
+ : never;
@@ -2,10 +2,10 @@
2
2
  import type { Simplify, WithoutIndexSignature } from '../types';
3
3
 
4
4
  /**
5
- * @link https://github.com/remix-run/remix/blob/2248669ed59fd716e267ea41df5d665d4781f4a9/packages/remix-server-runtime/serialize.ts
5
+ * @see https://github.com/remix-run/remix/blob/2248669ed59fd716e267ea41df5d665d4781f4a9/packages/remix-server-runtime/serialize.ts
6
6
  */
7
7
  type JsonPrimitive = boolean | number | string | null;
8
- // eslint-disable-next-line @typescript-eslint/ban-types
8
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
9
9
  type NonJsonPrimitive = Function | symbol | undefined;
10
10
  /*
11
11
  * `any` is the only type that can let you equate `0` with `1`
@@ -26,7 +26,7 @@ type IsRecord<T extends object> = keyof WithoutIndexSignature<T> extends never
26
26
  export type Serialize<T> =
27
27
  IsAny<T> extends true ? any :
28
28
  unknown extends T ? unknown :
29
- T extends AsyncGenerator<infer $T, infer $Return, infer $Next> ? AsyncGenerator<Serialize<$T>, Serialize<$Return>, Serialize<$Next>> :
29
+ T extends AsyncIterable<infer $T, infer $Return, infer $Next> ? AsyncIterable<Serialize<$T>, Serialize<$Return>, Serialize<$Next>> :
30
30
  T extends JsonReturnable ? T :
31
31
  T extends Map<any, any> | Set<any> ? object :
32
32
  T extends NonJsonPrimitive ? never :
@@ -119,5 +119,5 @@ type UndefinedToOptional<T extends object> =
119
119
  (ExactOptionalPropertyTypes extends true
120
120
  ? HandleIndexSignature<T> & HandleUndefined<WithoutIndexSignature<T>>
121
121
  : HasIndexSignature<T> extends true
122
- ? HandleIndexSignature<T>
123
- : HandleUndefined<T>);
122
+ ? HandleIndexSignature<T>
123
+ : HandleUndefined<T>);
@@ -1,9 +1,10 @@
1
1
  import type { TRPCError } from '../error/TRPCError';
2
2
  import type { TRPC_ERROR_CODES_BY_KEY, TRPCResponse } from '../rpc';
3
3
  import { TRPC_ERROR_CODES_BY_NUMBER } from '../rpc';
4
+ import type { InvertKeyValue, ValueOf } from '../types';
4
5
  import { isObject } from '../utils';
5
6
 
6
- const JSONRPC2_TO_HTTP_CODE: Record<
7
+ export const JSONRPC2_TO_HTTP_CODE: Record<
7
8
  keyof typeof TRPC_ERROR_CODES_BY_KEY,
8
9
  number
9
10
  > = {
@@ -28,11 +29,42 @@ const JSONRPC2_TO_HTTP_CODE: Record<
28
29
  GATEWAY_TIMEOUT: 504,
29
30
  };
30
31
 
31
- function getStatusCodeFromKey(code: keyof typeof TRPC_ERROR_CODES_BY_KEY) {
32
+ export const HTTP_CODE_TO_JSONRPC2: InvertKeyValue<
33
+ typeof JSONRPC2_TO_HTTP_CODE
34
+ > = {
35
+ 400: 'BAD_REQUEST',
36
+ 401: 'UNAUTHORIZED',
37
+ 403: 'FORBIDDEN',
38
+ 404: 'NOT_FOUND',
39
+ 405: 'METHOD_NOT_SUPPORTED',
40
+ 408: 'TIMEOUT',
41
+ 409: 'CONFLICT',
42
+ 412: 'PRECONDITION_FAILED',
43
+ 413: 'PAYLOAD_TOO_LARGE',
44
+ 415: 'UNSUPPORTED_MEDIA_TYPE',
45
+ 422: 'UNPROCESSABLE_CONTENT',
46
+ 429: 'TOO_MANY_REQUESTS',
47
+ 499: 'CLIENT_CLOSED_REQUEST',
48
+ 500: 'INTERNAL_SERVER_ERROR',
49
+ 501: 'NOT_IMPLEMENTED',
50
+ 502: 'BAD_GATEWAY',
51
+ 503: 'SERVICE_UNAVAILABLE',
52
+ 504: 'GATEWAY_TIMEOUT',
53
+ } as const;
54
+
55
+ export function getStatusCodeFromKey(
56
+ code: keyof typeof TRPC_ERROR_CODES_BY_KEY,
57
+ ) {
32
58
  return JSONRPC2_TO_HTTP_CODE[code] ?? 500;
33
59
  }
34
60
 
35
- export function getHTTPStatusCode(json: TRPCResponse | TRPCResponse[]): number {
61
+ export function getStatusKeyFromCode(
62
+ code: keyof typeof HTTP_CODE_TO_JSONRPC2,
63
+ ): ValueOf<typeof HTTP_CODE_TO_JSONRPC2> {
64
+ return HTTP_CODE_TO_JSONRPC2[code] ?? 'INTERNAL_SERVER_ERROR';
65
+ }
66
+
67
+ export function getHTTPStatusCode(json: TRPCResponse | TRPCResponse[]) {
36
68
  const arr = Array.isArray(json) ? json : [json];
37
69
  const httpStatuses = new Set<number>(
38
70
  arr.map((res) => {
@@ -53,7 +85,8 @@ export function getHTTPStatusCode(json: TRPCResponse | TRPCResponse[]): number {
53
85
 
54
86
  const httpStatus = httpStatuses.values().next().value;
55
87
 
56
- return httpStatus;
88
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
89
+ return httpStatus!;
57
90
  }
58
91
 
59
92
  export function getHTTPStatusCodeFromError(error: TRPCError) {
@@ -0,0 +1,7 @@
1
+ import { isObject } from '../utils';
2
+
3
+ export function isAbortError(
4
+ error: unknown,
5
+ ): error is DOMException | Error | { name: 'AbortError' } {
6
+ return isObject(error) && error['name'] === 'AbortError';
7
+ }