@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
@@ -7,57 +7,118 @@ export interface IncomingMessageWithBody extends http.IncomingMessage {
7
7
  */
8
8
  body?: unknown;
9
9
  }
10
- /**
11
- * Convert an incoming message to a body stream with a max size
12
- */
13
- function incomingMessageToBodyStream(
14
- req: IncomingMessageWithBody,
15
- opts: { maxBodySize: number | null },
16
- ) {
17
- type Value = Buffer | Uint8Array | string | null;
10
+
11
+ function createBody(
12
+ req: http.IncomingMessage,
13
+ opts: {
14
+ /**
15
+ * Max body size in bytes. If the body is larger than this, the request will be aborted
16
+ */
17
+ maxBodySize: number | null;
18
+ },
19
+ ): RequestInit['body'] {
20
+ // Some adapters will pre-parse the body and add it to the request object
21
+ if ('body' in req) {
22
+ // If the body is already a string, return it directly
23
+ if (typeof req.body === 'string') {
24
+ return req.body;
25
+ }
26
+ // If body exists but isn't a string, stringify it as JSON
27
+ else if (req.body !== undefined) {
28
+ return JSON.stringify(req.body);
29
+ }
30
+ // If body property exists but is undefined, return undefined
31
+ return undefined;
32
+ }
18
33
  let size = 0;
19
- const maxBodySize = opts.maxBodySize;
20
34
  let hasClosed = false;
21
35
 
22
- const stream = new ReadableStream<Value>({
36
+ return new ReadableStream({
23
37
  start(controller) {
24
- req.on('data', (chunk) => {
38
+ const onData = (chunk: Buffer) => {
25
39
  size += chunk.length;
26
- if (maxBodySize != null && size > maxBodySize) {
27
- controller.error(
28
- new TRPCError({
29
- code: 'PAYLOAD_TOO_LARGE',
30
- }),
40
+ if (!opts.maxBodySize || size <= opts.maxBodySize) {
41
+ controller.enqueue(
42
+ new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength),
31
43
  );
32
- // an error is thrown if we try to close the controller after
33
- // erroring, so track the closure
34
- hasClosed = true;
35
44
  return;
36
45
  }
37
- controller.enqueue(chunk);
38
- });
39
- req.once('end', () => {
46
+ controller.error(
47
+ new TRPCError({
48
+ code: 'PAYLOAD_TOO_LARGE',
49
+ }),
50
+ );
51
+ hasClosed = true;
52
+ req.off('data', onData);
53
+ req.off('end', onEnd);
54
+ };
55
+
56
+ const onEnd = () => {
40
57
  if (hasClosed) {
41
58
  return;
42
59
  }
43
60
  hasClosed = true;
61
+ req.off('data', onData);
62
+ req.off('end', onEnd);
44
63
  controller.close();
45
- });
64
+ };
65
+
66
+ req.on('data', onData);
67
+ req.on('end', onEnd);
46
68
  },
47
69
  cancel() {
48
70
  req.destroy();
49
71
  },
50
72
  });
73
+ }
74
+ export function createURL(req: http.IncomingMessage): URL {
75
+ try {
76
+ const protocol =
77
+ req.socket && 'encrypted' in req.socket && req.socket.encrypted
78
+ ? 'https:'
79
+ : 'http:';
80
+
81
+ const host = req.headers.host ?? 'localhost';
82
+
83
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
84
+ return new URL(req.url!, `${protocol}//${host}`);
85
+ } catch (cause) {
86
+ throw new TRPCError({
87
+ code: 'BAD_REQUEST',
88
+ message: 'Invalid URL',
89
+ cause,
90
+ });
91
+ }
92
+ }
93
+
94
+ function createHeaders(incoming: http.IncomingHttpHeaders): Headers {
95
+ const headers = new Headers();
96
+
97
+ for (const key in incoming) {
98
+ const value = incoming[key];
99
+ if (typeof key === 'string' && key.startsWith(':')) {
100
+ // Skip HTTP/2 pseudo-headers
101
+ continue;
102
+ }
51
103
 
52
- return stream;
104
+ if (Array.isArray(value)) {
105
+ for (const item of value) {
106
+ headers.append(key, item);
107
+ }
108
+ } else if (value != null) {
109
+ headers.append(key, value);
110
+ }
111
+ }
112
+
113
+ return headers;
53
114
  }
54
115
 
55
- const bodyMethods = ['POST', 'PUT', 'PATCH'];
56
116
  /**
57
117
  * Convert an [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) to a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
58
118
  */
59
119
  export function incomingMessageToRequest(
60
120
  req: http.IncomingMessage,
121
+ res: http.ServerResponse,
61
122
  opts: {
62
123
  /**
63
124
  * Max body size in bytes. If the body is larger than this, the request will be aborted
@@ -66,29 +127,38 @@ export function incomingMessageToRequest(
66
127
  },
67
128
  ): Request {
68
129
  const ac = new AbortController();
69
- const headers = new Headers(req.headers as any);
70
- const url = `http://${headers.get('host')}${req.url}`;
71
- req.once('aborted', () => {
130
+
131
+ const onAbort = () => {
132
+ res.off('close', onAbort);
133
+ req.socket.off('end', onAbort);
134
+
135
+ // abort the request
72
136
  ac.abort();
73
- });
137
+ };
138
+
139
+ res.once('close', onAbort);
140
+ req.socket.once('end', onAbort);
141
+
142
+ // Get host from either regular header or HTTP/2 pseudo-header
143
+ const url = createURL(req);
74
144
 
75
145
  const init: RequestInit = {
76
- headers,
146
+ headers: createHeaders(req.headers),
77
147
  method: req.method,
78
148
  signal: ac.signal,
79
- // @ts-expect-error this is fine
80
- duplex: 'half',
81
149
  };
82
150
 
83
- if (req.method && bodyMethods.includes(req.method)) {
84
- if (!('body' in req)) {
85
- init.body = incomingMessageToBodyStream(req, opts);
86
- } else if (typeof req.body === 'string') {
87
- init.body = req.body;
88
- } else if (req.body !== undefined) {
89
- init.body = JSON.stringify(req.body);
90
- }
151
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
152
+ init.body = createBody(req, opts);
153
+
154
+ // init.duplex = 'half' must be set when body is a ReadableStream, and Node follows the spec.
155
+ // However, this property is not defined in the TypeScript types for RequestInit, so we have
156
+ // to cast it here in order to set it without a type error.
157
+ // See https://fetch.spec.whatwg.org/#dom-requestinit-duplex
158
+ // @ts-expect-error this is fine
159
+ init.duplex = 'half';
91
160
  }
161
+
92
162
  const request = new Request(url, init);
93
163
 
94
164
  return request;
@@ -10,90 +10,112 @@
10
10
 
11
11
  // @trpc/server
12
12
 
13
- import { getTRPCErrorFromUnknown, type AnyRouter } from '../../@trpc/server';
13
+ import {
14
+ getTRPCErrorFromUnknown,
15
+ transformTRPCResponse,
16
+ type AnyRouter,
17
+ } from '../../@trpc/server';
14
18
  import type { ResolveHTTPRequestOptionsContextFn } from '../../@trpc/server/http';
15
19
  import { resolveResponse } from '../../@trpc/server/http';
20
+ // eslint-disable-next-line no-restricted-imports
21
+ import { getErrorShape, run } from '../../unstable-core-do-not-import';
16
22
  import { incomingMessageToRequest } from './incomingMessageToRequest';
17
23
  import type {
18
24
  NodeHTTPRequest,
19
25
  NodeHTTPRequestHandlerOptions,
20
26
  NodeHTTPResponse,
21
27
  } from './types';
28
+ import { writeResponse } from './writeResponse';
22
29
 
23
- export async function nodeHTTPRequestHandler<
30
+ /**
31
+ * @internal
32
+ */
33
+ export function internal_exceptionHandler<
24
34
  TRouter extends AnyRouter,
25
35
  TRequest extends NodeHTTPRequest,
26
36
  TResponse extends NodeHTTPResponse,
27
37
  >(opts: NodeHTTPRequestHandlerOptions<TRouter, TRequest, TResponse>) {
28
- const handleViaMiddleware = opts.middleware ?? ((_req, _res, next) => next());
38
+ return (cause: unknown) => {
39
+ const { res, req } = opts;
40
+ const error = getTRPCErrorFromUnknown(cause);
29
41
 
30
- return handleViaMiddleware(opts.req, opts.res, async (err) => {
31
- const req = incomingMessageToRequest(opts.req, {
32
- maxBodySize: opts.maxBodySize ?? null,
42
+ const shape = getErrorShape({
43
+ config: opts.router._def._config,
44
+ error,
45
+ type: 'unknown',
46
+ path: undefined,
47
+ input: undefined,
48
+ ctx: undefined,
33
49
  });
34
50
 
35
- // Build tRPC dependencies
36
- const createContext: ResolveHTTPRequestOptionsContextFn<TRouter> = async (
37
- innerOpts,
38
- ) => {
39
- return await opts.createContext?.({
40
- ...opts,
41
- ...innerOpts,
42
- });
43
- };
44
-
45
- const response = await resolveResponse({
46
- ...opts,
51
+ opts.onError?.({
47
52
  req,
48
- error: err ? getTRPCErrorFromUnknown(err) : null,
49
- createContext,
50
- onError(o) {
51
- opts?.onError?.({
52
- ...o,
53
- req: opts.req,
54
- });
55
- },
53
+ error,
54
+ type: 'unknown',
55
+ path: undefined,
56
+ input: undefined,
57
+ ctx: undefined,
56
58
  });
57
59
 
58
- const { res } = opts;
59
- if (res.statusCode === 200) {
60
- // if the status code is set, we assume that it's been manually overridden
61
- res.statusCode = response.status;
62
- }
63
- for (const [key, value] of response.headers) {
64
- res.setHeader(key, value);
65
- }
66
- if (response.body) {
67
- const reader = response.body.getReader();
68
- const onAbort = () => {
69
- // cancelling the reader will cause the whole stream to be cancelled
70
- reader.cancel().catch(() => {
71
- // console.error('reader.cancel() error', err);
72
- });
73
- };
74
- req.signal.addEventListener('abort', onAbort, {
75
- once: true,
76
- });
60
+ const transformed = transformTRPCResponse(opts.router._def._config, {
61
+ error: shape,
62
+ });
63
+
64
+ res.statusCode = shape.data.httpStatus;
65
+ res.end(JSON.stringify(transformed));
66
+ };
67
+ }
68
+
69
+ /**
70
+ * @remark the promise never rejects
71
+ */
72
+ export async function nodeHTTPRequestHandler<
73
+ TRouter extends AnyRouter,
74
+ TRequest extends NodeHTTPRequest,
75
+ TResponse extends NodeHTTPResponse,
76
+ >(opts: NodeHTTPRequestHandlerOptions<TRouter, TRequest, TResponse>) {
77
+ return new Promise<void>((resolve) => {
78
+ const handleViaMiddleware =
79
+ opts.middleware ?? ((_req, _res, next) => next());
77
80
 
78
- while (true) {
79
- const { done, value } = await reader.read();
81
+ opts.res.once('finish', () => {
82
+ resolve();
83
+ });
84
+ return handleViaMiddleware(opts.req, opts.res, (err: unknown) => {
85
+ run(async () => {
86
+ const request = incomingMessageToRequest(opts.req, opts.res, {
87
+ maxBodySize: opts.maxBodySize ?? null,
88
+ });
80
89
 
81
- if (done) {
82
- break;
83
- }
84
- if (!res.writable) {
85
- break;
86
- }
87
- if (res.write(value) === false) {
88
- await new Promise<void>((resolve) => {
89
- res.once('drain', resolve);
90
+ // Build tRPC dependencies
91
+ const createContext: ResolveHTTPRequestOptionsContextFn<
92
+ TRouter
93
+ > = async (innerOpts) => {
94
+ return await opts.createContext?.({
95
+ ...opts,
96
+ ...innerOpts,
90
97
  });
91
- }
92
- // IMPORTANT - flush the response buffer, otherwise the client will not receive the data until `.end()`
93
- res.flush?.();
94
- }
95
- req.signal.removeEventListener('abort', onAbort);
96
- }
97
- res.end();
98
+ };
99
+
100
+ const response = await resolveResponse({
101
+ ...opts,
102
+ req: request,
103
+ error: err ? getTRPCErrorFromUnknown(err) : null,
104
+ createContext,
105
+ onError(o) {
106
+ opts?.onError?.({
107
+ ...o,
108
+ req: opts.req,
109
+ });
110
+ },
111
+ });
112
+
113
+ await writeResponse({
114
+ request,
115
+ response,
116
+ rawResponse: opts.res,
117
+ });
118
+ }).catch(internal_exceptionHandler(opts));
119
+ });
98
120
  });
99
121
  }
@@ -0,0 +1,94 @@
1
+ // eslint-disable-next-line no-restricted-imports
2
+ import { isAbortError } from '../../unstable-core-do-not-import';
3
+ import type { NodeHTTPResponse } from './types';
4
+
5
+ async function writeResponseBodyChunk(
6
+ res: NodeHTTPResponse,
7
+ chunk: Uint8Array,
8
+ ) {
9
+ // useful for debugging 🙃
10
+ // console.debug('writing', new TextDecoder().decode(chunk));
11
+
12
+ if (res.write(chunk) === false) {
13
+ await new Promise<void>((resolve, reject) => {
14
+ const onError = (err: unknown) => {
15
+ reject(err);
16
+ cleanup();
17
+ };
18
+ const onDrain = () => {
19
+ resolve();
20
+ cleanup();
21
+ };
22
+ const cleanup = () => {
23
+ res.off('error', onError);
24
+ res.off('drain', onDrain);
25
+ };
26
+ res.once('error', onError);
27
+ res.once('drain', onDrain);
28
+ });
29
+ }
30
+ }
31
+ /**
32
+ * @internal
33
+ */
34
+
35
+ export async function writeResponseBody(opts: {
36
+ res: NodeHTTPResponse;
37
+ signal: AbortSignal;
38
+ body: NonNullable<Response['body']>;
39
+ }) {
40
+ const { res } = opts;
41
+
42
+ try {
43
+ const writableStream = new WritableStream({
44
+ async write(chunk) {
45
+ await writeResponseBodyChunk(res, chunk);
46
+ res.flush?.();
47
+ },
48
+ });
49
+
50
+ await opts.body.pipeTo(writableStream, {
51
+ signal: opts.signal,
52
+ });
53
+ } catch (err) {
54
+ if (isAbortError(err)) {
55
+ return;
56
+ }
57
+ throw err;
58
+ }
59
+ }
60
+ /**
61
+ * @internal
62
+ */
63
+
64
+ export async function writeResponse(opts: {
65
+ request: Request;
66
+ response: Response;
67
+ rawResponse: NodeHTTPResponse;
68
+ }) {
69
+ const { response, rawResponse } = opts;
70
+
71
+ // Only override status code if it hasn't been explicitly set in a procedure etc
72
+ if (rawResponse.statusCode === 200) {
73
+ rawResponse.statusCode = response.status;
74
+ }
75
+ for (const [key, value] of response.headers) {
76
+ rawResponse.setHeader(key, value);
77
+ }
78
+ try {
79
+ if (response.body) {
80
+ await writeResponseBody({
81
+ res: rawResponse,
82
+ signal: opts.request.signal,
83
+ body: response.body,
84
+ });
85
+ }
86
+ } catch (err) {
87
+ if (!rawResponse.headersSent) {
88
+ rawResponse.statusCode = 500;
89
+ }
90
+ throw err;
91
+ } finally {
92
+ rawResponse.end();
93
+ }
94
+ }
@@ -7,16 +7,21 @@
7
7
  * import type { HTTPBaseHandlerOptions } from '@trpc/server/http'
8
8
  * ```
9
9
  */
10
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
10
+
11
11
  import http from 'http';
12
12
  // @trpc/server
13
- import type { AnyRouter } from '../@trpc/server';
14
- import { toURL } from '../@trpc/server/http';
13
+ import { type AnyRouter } from '../@trpc/server';
14
+ // eslint-disable-next-line no-restricted-imports
15
+ import { run } from '../unstable-core-do-not-import';
15
16
  import type {
16
17
  NodeHTTPCreateContextFnOptions,
17
18
  NodeHTTPHandlerOptions,
18
19
  } from './node-http';
19
- import { nodeHTTPRequestHandler } from './node-http';
20
+ import {
21
+ createURL,
22
+ internal_exceptionHandler,
23
+ nodeHTTPRequestHandler,
24
+ } from './node-http';
20
25
 
21
26
  export type CreateHTTPHandlerOptions<TRouter extends AnyRouter> =
22
27
  NodeHTTPHandlerOptions<TRouter, http.IncomingMessage, http.ServerResponse>;
@@ -26,28 +31,40 @@ export type CreateHTTPContextOptions = NodeHTTPCreateContextFnOptions<
26
31
  http.ServerResponse
27
32
  >;
28
33
 
34
+ /**
35
+ * @internal
36
+ */
29
37
  export function createHTTPHandler<TRouter extends AnyRouter>(
30
38
  opts: CreateHTTPHandlerOptions<TRouter>,
31
- ) {
32
- return async (req: http.IncomingMessage, res: http.ServerResponse) => {
33
- const url = toURL(req.url!);
39
+ ): http.RequestListener {
40
+ return (req, res) => {
41
+ let path = '';
42
+ run(async () => {
43
+ const url = createURL(req);
34
44
 
35
- // get procedure path and remove the leading slash
36
- // /procedure -> procedure
37
- const path = url.pathname.slice(1);
45
+ // get procedure path and remove the leading slash
46
+ // /procedure -> procedure
47
+ path = url.pathname.slice(1);
38
48
 
39
- await nodeHTTPRequestHandler({
40
- ...(opts as any),
41
- req,
42
- res,
43
- path,
44
- });
49
+ await nodeHTTPRequestHandler({
50
+ ...(opts as any),
51
+ req,
52
+ res,
53
+ path,
54
+ });
55
+ }).catch(
56
+ internal_exceptionHandler({
57
+ req,
58
+ res,
59
+ path,
60
+ ...opts,
61
+ }),
62
+ );
45
63
  };
46
64
  }
47
65
 
48
66
  export function createHTTPServer<TRouter extends AnyRouter>(
49
67
  opts: CreateHTTPHandlerOptions<TRouter>,
50
68
  ) {
51
- const handler = createHTTPHandler(opts);
52
- return http.createServer(handler);
69
+ return http.createServer(createHTTPHandler(opts));
53
70
  }