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

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 +415 -313
  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
@@ -1,8 +1,10 @@
1
- import { getTRPCErrorFromUnknown } from '../error/TRPCError';
1
+ import { Unpromise } from '../../vendor/unpromise';
2
2
  import { isAsyncIterable, isFunction, isObject, run } from '../utils';
3
+ import { iteratorResource } from './utils/asyncIterable';
3
4
  import type { Deferred } from './utils/createDeferred';
4
5
  import { createDeferred } from './utils/createDeferred';
5
- import { createReadableStream } from './utils/createReadableStream';
6
+ import { makeAsyncResource, makeResource } from './utils/disposable';
7
+ import { readableStreamFrom } from './utils/readableStreamFrom';
6
8
 
7
9
  /**
8
10
  * A subset of the standard ReadableStream properties needed by tRPC internally.
@@ -19,6 +21,8 @@ export type NodeJSReadableStreamEsque = {
19
21
  ): NodeJSReadableStreamEsque;
20
22
  };
21
23
 
24
+ // ---------- types
25
+
22
26
  // ---------- types
23
27
  const CHUNK_VALUE_TYPE_PROMISE = 0;
24
28
  type CHUNK_VALUE_TYPE_PROMISE = typeof CHUNK_VALUE_TYPE_PROMISE;
@@ -32,8 +36,8 @@ type PROMISE_STATUS_REJECTED = typeof PROMISE_STATUS_REJECTED;
32
36
 
33
37
  const ASYNC_ITERABLE_STATUS_RETURN = 0;
34
38
  type ASYNC_ITERABLE_STATUS_RETURN = typeof ASYNC_ITERABLE_STATUS_RETURN;
35
- const ASYNC_ITERABLE_STATUS_VALUE = 1;
36
- type ASYNC_ITERABLE_STATUS_VALUE = typeof ASYNC_ITERABLE_STATUS_VALUE;
39
+ const ASYNC_ITERABLE_STATUS_YIELD = 1;
40
+ type ASYNC_ITERABLE_STATUS_YIELD = typeof ASYNC_ITERABLE_STATUS_YIELD;
37
41
  const ASYNC_ITERABLE_STATUS_ERROR = 2;
38
42
  type ASYNC_ITERABLE_STATUS_ERROR = typeof ASYNC_ITERABLE_STATUS_ERROR;
39
43
 
@@ -54,31 +58,31 @@ type ChunkDefinition = [
54
58
  type: ChunkValueType,
55
59
  chunkId: ChunkIndex,
56
60
  ];
57
- type DehydratedValue = [
61
+ type EncodedValue = [
58
62
  // data
59
- [unknown],
63
+ [unknown] | [],
60
64
  // chunk descriptions
61
65
  ...ChunkDefinition[],
62
66
  ];
63
67
 
64
- type Head = Record<string, DehydratedValue>;
68
+ type Head = Record<string, EncodedValue>;
65
69
  type PromiseChunk =
66
70
  | [
67
71
  chunkIndex: ChunkIndex,
68
72
  status: PROMISE_STATUS_FULFILLED,
69
- value: DehydratedValue,
73
+ value: EncodedValue,
70
74
  ]
71
75
  | [chunkIndex: ChunkIndex, status: PROMISE_STATUS_REJECTED, error: unknown];
72
76
  type IterableChunk =
73
77
  | [
74
78
  chunkIndex: ChunkIndex,
75
79
  status: ASYNC_ITERABLE_STATUS_RETURN,
76
- value: DehydratedValue,
80
+ value: EncodedValue,
77
81
  ]
78
82
  | [
79
83
  chunkIndex: ChunkIndex,
80
- status: ASYNC_ITERABLE_STATUS_VALUE,
81
- value: DehydratedValue,
84
+ status: ASYNC_ITERABLE_STATUS_YIELD,
85
+ value: EncodedValue,
82
86
  ]
83
87
  | [
84
88
  chunkIndex: ChunkIndex,
@@ -117,128 +121,98 @@ class MaxDepthError extends Error {
117
121
  }
118
122
  }
119
123
 
120
- function createBatchStreamProducer(opts: ProducerOptions) {
124
+ async function* createBatchStreamProducer(
125
+ opts: ProducerOptions,
126
+ ): AsyncIterable<Head | ChunkData, void> {
121
127
  const { data } = opts;
122
128
  let counter = 0 as ChunkIndex;
123
129
  const placeholder = 0 as PlaceholderValue;
124
130
 
125
- const stream = createReadableStream<ChunkData>();
126
- const pending = new Set<ChunkIndex>();
127
-
128
- function maybeClose() {
129
- if (pending.size === 0 && !stream.cancelled()) {
130
- stream.controller.close();
131
- }
132
- }
133
- function dehydratePromise(
134
- promise: Promise<unknown>,
135
- path: (string | number)[],
131
+ await using queue = makeAsyncResource(
132
+ new Set<{
133
+ iterator: AsyncIterator<ChunkData, ChunkData>;
134
+ nextPromise: Promise<IteratorResult<ChunkData, ChunkData>>;
135
+ }>(),
136
+ async () => {
137
+ await Promise.all(Array.from(queue).map((it) => it.iterator.return?.()));
138
+ },
139
+ );
140
+ function registerAsync(
141
+ callback: (idx: ChunkIndex) => AsyncIterable<ChunkData, ChunkData>,
136
142
  ) {
137
- //
138
- const error = checkMaxDepth(path);
139
- if (error) {
140
- promise.catch(() => {
141
- // ignore
142
- });
143
- promise = Promise.reject(error);
144
- }
145
143
  const idx = counter++ as ChunkIndex;
146
- pending.add(idx);
147
144
 
148
- Promise.race([promise, stream.cancelledPromise])
149
- .then((it) => {
150
- if (it === null) {
151
- return;
152
- }
153
- stream.controller.enqueue([
154
- idx,
155
- PROMISE_STATUS_FULFILLED,
156
- dehydrate(it, path),
157
- ]);
158
- })
159
- .catch((cause) => {
145
+ const iterator = callback(idx)[Symbol.asyncIterator]();
146
+
147
+ const nextPromise = iterator.next();
148
+
149
+ nextPromise.catch(() => {
150
+ // prevent unhandled promise rejection
151
+ });
152
+ queue.add({
153
+ iterator,
154
+ nextPromise,
155
+ });
156
+
157
+ return idx;
158
+ }
159
+
160
+ function encodePromise(promise: Promise<unknown>, path: (string | number)[]) {
161
+ return registerAsync(async function* (idx) {
162
+ const error = checkMaxDepth(path);
163
+ if (error) {
164
+ // Catch any errors from the original promise to ensure they're reported
165
+ promise.catch((cause) => {
166
+ opts.onError?.({ error: cause, path });
167
+ });
168
+ // Replace the promise with a rejected one containing the max depth error
169
+ promise = Promise.reject(error);
170
+ }
171
+ try {
172
+ const next = await promise;
173
+ return [idx, PROMISE_STATUS_FULFILLED, encode(next, path)];
174
+ } catch (cause) {
160
175
  opts.onError?.({ error: cause, path });
161
- stream.controller.enqueue([
176
+ return [
162
177
  idx,
163
178
  PROMISE_STATUS_REJECTED,
164
179
  opts.formatError?.({ error: cause, path }),
165
- ]);
166
- })
167
- .finally(() => {
168
- pending.delete(idx);
169
- maybeClose();
170
- });
171
- return idx;
180
+ ];
181
+ }
182
+ });
172
183
  }
173
- function dehydrateAsyncIterable(
184
+ function encodeAsyncIterable(
174
185
  iterable: AsyncIterable<unknown>,
175
186
  path: (string | number)[],
176
187
  ) {
177
- const error = checkMaxDepth(path);
178
- if (error) {
179
- iterable = {
180
- [Symbol.asyncIterator]() {
181
- throw error;
182
- },
183
- };
184
- }
185
- const idx = counter++ as ChunkIndex;
186
- pending.add(idx);
187
- run(async () => {
188
- const iterator = iterable[Symbol.asyncIterator]();
189
-
190
- while (true) {
191
- const next = await Promise.race([
192
- iterator.next().catch(getTRPCErrorFromUnknown),
193
- stream.cancelledPromise,
194
- ]);
195
-
196
- if (next instanceof Error) {
197
- opts.onError?.({ error: next, path });
198
-
199
- stream.controller.enqueue([
200
- idx,
201
- ASYNC_ITERABLE_STATUS_ERROR,
202
- opts.formatError?.({ error: next, path }),
203
- ]);
204
- return;
205
- }
206
- if (next === 'cancelled') {
207
- await iterator.return?.();
208
- break;
209
- }
210
- if (next.done) {
211
- stream.controller.enqueue([
212
- idx,
213
- ASYNC_ITERABLE_STATUS_RETURN,
214
- dehydrate(next.value, path),
215
- ]);
216
- break;
188
+ return registerAsync(async function* (idx) {
189
+ const error = checkMaxDepth(path);
190
+ if (error) {
191
+ throw error;
192
+ }
193
+ await using iterator = iteratorResource(iterable);
194
+
195
+ try {
196
+ while (true) {
197
+ const next = await iterator.next();
198
+ if (next.done) {
199
+ return [
200
+ idx,
201
+ ASYNC_ITERABLE_STATUS_RETURN,
202
+ encode(next.value, path),
203
+ ];
204
+ }
205
+ yield [idx, ASYNC_ITERABLE_STATUS_YIELD, encode(next.value, path)];
217
206
  }
218
- stream.controller.enqueue([
207
+ } catch (cause) {
208
+ opts.onError?.({ error: cause, path });
209
+ return [
219
210
  idx,
220
- ASYNC_ITERABLE_STATUS_VALUE,
221
- dehydrate(next.value, path),
222
- ]);
211
+ ASYNC_ITERABLE_STATUS_ERROR,
212
+ opts.formatError?.({ error: cause, path }),
213
+ ];
223
214
  }
224
-
225
- pending.delete(idx);
226
- maybeClose();
227
- }).catch((cause) => {
228
- // this shouldn't happen, but node crashes if we don't catch it
229
- opts.onError?.({
230
- error: new Error(
231
- 'You found a bug - please report it on https://github.com/trpc/trpc',
232
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
233
- // @ts-ignore https://github.com/tc39/proposal-error-cause
234
- {
235
- cause,
236
- },
237
- ),
238
- path,
239
- });
240
215
  });
241
- return idx;
242
216
  }
243
217
  function checkMaxDepth(path: (string | number)[]) {
244
218
  if (opts.maxDepth && path.length > opts.maxDepth) {
@@ -246,12 +220,12 @@ function createBatchStreamProducer(opts: ProducerOptions) {
246
220
  }
247
221
  return null;
248
222
  }
249
- function dehydrateChunk(
223
+ function encodeAsync(
250
224
  value: unknown,
251
225
  path: (string | number)[],
252
226
  ): null | [type: ChunkValueType, chunkId: ChunkIndex] {
253
227
  if (isPromise(value)) {
254
- return [CHUNK_VALUE_TYPE_PROMISE, dehydratePromise(value, path)];
228
+ return [CHUNK_VALUE_TYPE_PROMISE, encodePromise(value, path)];
255
229
  }
256
230
  if (isAsyncIterable(value)) {
257
231
  if (opts.maxDepth && path.length >= opts.maxDepth) {
@@ -259,26 +233,26 @@ function createBatchStreamProducer(opts: ProducerOptions) {
259
233
  }
260
234
  return [
261
235
  CHUNK_VALUE_TYPE_ASYNC_ITERABLE,
262
- dehydrateAsyncIterable(value, path),
236
+ encodeAsyncIterable(value, path),
263
237
  ];
264
238
  }
265
239
  return null;
266
240
  }
267
- function dehydrate(
268
- value: unknown,
269
- path: (string | number)[],
270
- ): DehydratedValue {
271
- const reg = dehydrateChunk(value, path);
272
- if (reg) {
273
- return [[placeholder], [null, ...reg]];
241
+ function encode(value: unknown, path: (string | number)[]): EncodedValue {
242
+ if (value === undefined) {
243
+ return [[]];
274
244
  }
275
245
  if (!isObject(value)) {
276
246
  return [[value]];
277
247
  }
248
+ const reg = encodeAsync(value, path);
249
+ if (reg) {
250
+ return [[placeholder], [null, ...reg]];
251
+ }
278
252
  const newObj = {} as Record<string, unknown>;
279
253
  const asyncValues: ChunkDefinition[] = [];
280
254
  for (const [key, item] of Object.entries(value)) {
281
- const transformed = dehydrateChunk(item, [...path, key]);
255
+ const transformed = encodeAsync(item, [...path, key]);
282
256
  if (!transformed) {
283
257
  newObj[key] = item;
284
258
  continue;
@@ -291,21 +265,37 @@ function createBatchStreamProducer(opts: ProducerOptions) {
291
265
 
292
266
  const newHead: Head = {};
293
267
  for (const [key, item] of Object.entries(data)) {
294
- newHead[key] = dehydrate(item, [key]);
268
+ newHead[key] = encode(item, [key]);
295
269
  }
296
270
 
297
- return [newHead, stream.readable] as const;
271
+ yield newHead;
272
+
273
+ // Process all async iterables in parallel by racing their next values
274
+ while (queue.size > 0) {
275
+ // Race all iterators to get the next value from any of them
276
+ const [entry, res] = await Unpromise.race(
277
+ Array.from(queue).map(async (it) => [it, await it.nextPromise] as const),
278
+ );
279
+
280
+ yield res.value;
281
+
282
+ // Remove current iterator and re-add if not done
283
+ queue.delete(entry);
284
+ if (!res.done) {
285
+ entry.nextPromise = entry.iterator.next();
286
+ queue.add(entry);
287
+ }
288
+ }
298
289
  }
299
290
  /**
300
291
  * JSON Lines stream producer
301
292
  * @see https://jsonlines.org/
302
293
  */
303
294
  export function jsonlStreamProducer(opts: ProducerOptions) {
304
- let [head, stream] = createBatchStreamProducer(opts);
295
+ let stream = readableStreamFrom(createBatchStreamProducer(opts));
305
296
 
306
297
  const { serialize } = opts;
307
298
  if (serialize) {
308
- head = serialize(head);
309
299
  stream = stream.pipeThrough(
310
300
  new TransformStream({
311
301
  transform(chunk, controller) {
@@ -318,9 +308,6 @@ export function jsonlStreamProducer(opts: ProducerOptions) {
318
308
  return stream
319
309
  .pipeThrough(
320
310
  new TransformStream({
321
- start(controller) {
322
- controller.enqueue(JSON.stringify(head) + '\n');
323
- },
324
311
  transform(chunk, controller) {
325
312
  controller.enqueue(JSON.stringify(chunk) + '\n');
326
313
  },
@@ -346,17 +333,20 @@ export type ConsumerOnError = (opts: { error: unknown }) => void;
346
333
  const nodeJsStreamToReaderEsque = (source: NodeJSReadableStreamEsque) => {
347
334
  return {
348
335
  getReader() {
349
- const { readable, controller } = createReadableStream<Uint8Array>();
350
- source.on('data', (chunk) => {
351
- controller.enqueue(chunk);
352
- });
353
- source.on('end', () => {
354
- controller.close();
355
- });
356
- source.on('error', (error) => {
357
- controller.error(error);
336
+ const stream = new ReadableStream<Uint8Array>({
337
+ start(controller) {
338
+ source.on('data', (chunk) => {
339
+ controller.enqueue(chunk);
340
+ });
341
+ source.on('end', () => {
342
+ controller.close();
343
+ });
344
+ source.on('error', (error) => {
345
+ controller.error(error);
346
+ });
347
+ },
358
348
  });
359
- return readable.getReader();
349
+ return stream.getReader();
360
350
  },
361
351
  };
362
352
  };
@@ -420,6 +410,102 @@ function createConsumerStream<THead>(
420
410
  }),
421
411
  );
422
412
  }
413
+ /**
414
+ * Represents a chunk of data or stream interruption error that can be enqueued to a controller
415
+ */
416
+ type ControllerChunk = ChunkData | StreamInterruptedError;
417
+
418
+ /**
419
+ * Creates a handler for managing stream controllers and their lifecycle
420
+ */
421
+ function createStreamsManager(abortController: AbortController) {
422
+ const controllerMap = new Map<
423
+ ChunkIndex,
424
+ ReturnType<typeof createStreamController>
425
+ >();
426
+
427
+ /**
428
+ * Checks if there are no pending controllers or deferred promises
429
+ */
430
+ function isEmpty() {
431
+ return Array.from(controllerMap.values()).every((c) => c.closed);
432
+ }
433
+
434
+ /**
435
+ * Creates a stream controller
436
+ */
437
+ function createStreamController() {
438
+ let originalController: ReadableStreamDefaultController<ControllerChunk>;
439
+ const stream = new ReadableStream<ControllerChunk>({
440
+ start(controller) {
441
+ originalController = controller;
442
+ },
443
+ });
444
+
445
+ const streamController = {
446
+ enqueue: (v: ControllerChunk) => originalController.enqueue(v),
447
+ close: () => {
448
+ originalController.close();
449
+
450
+ // mark as closed and remove methods
451
+ Object.assign(streamController, {
452
+ closed: true,
453
+ close: () => {
454
+ // noop
455
+ },
456
+ enqueue: () => {
457
+ // noop
458
+ },
459
+ getReaderResource: null,
460
+ });
461
+
462
+ if (isEmpty()) {
463
+ abortController.abort();
464
+ }
465
+ },
466
+ closed: false,
467
+ getReaderResource: () => {
468
+ const reader = stream.getReader();
469
+
470
+ return makeResource(reader, () => {
471
+ reader.releaseLock();
472
+ streamController.close();
473
+ });
474
+ },
475
+ };
476
+
477
+ return streamController;
478
+ }
479
+
480
+ /**
481
+ * Gets or creates a stream controller
482
+ */
483
+ function getOrCreate(chunkId: ChunkIndex) {
484
+ let c = controllerMap.get(chunkId);
485
+ if (!c) {
486
+ c = createStreamController();
487
+ controllerMap.set(chunkId, c);
488
+ }
489
+ return c;
490
+ }
491
+
492
+ /**
493
+ * Cancels all pending controllers and rejects deferred promises
494
+ */
495
+ function cancelAll(reason: unknown) {
496
+ const error = new StreamInterruptedError(reason);
497
+ for (const controller of controllerMap.values()) {
498
+ controller.enqueue(error);
499
+ controller.close();
500
+ }
501
+ }
502
+
503
+ return {
504
+ getOrCreate,
505
+ isEmpty,
506
+ cancelAll,
507
+ };
508
+ }
423
509
 
424
510
  /**
425
511
  * JSON Lines stream consumer
@@ -430,7 +516,10 @@ export async function jsonlStreamConsumer<THead>(opts: {
430
516
  deserialize?: Deserialize;
431
517
  onError?: ConsumerOnError;
432
518
  formatError?: (opts: { error: unknown }) => Error;
433
- abortController: AbortController | null;
519
+ /**
520
+ * This `AbortController` will be triggered when there are no more listeners to the stream.
521
+ */
522
+ abortController: AbortController;
434
523
  }) {
435
524
  const { deserialize = (v) => v } = opts;
436
525
 
@@ -446,153 +535,72 @@ export async function jsonlStreamConsumer<THead>(opts: {
446
535
  }
447
536
  let headDeferred: null | Deferred<THead> = createDeferred();
448
537
 
449
- type ControllerChunk = ChunkData | StreamInterruptedError;
450
- type ChunkController = ReadableStreamDefaultController<ControllerChunk>;
451
- type ControllerWrapper = {
452
- controller: ChunkController;
453
- returned: boolean;
454
- };
455
- const chunkDeferred = new Map<ChunkIndex, Deferred<ControllerWrapper>>();
456
- const controllers = new Map<ChunkIndex, ControllerWrapper>();
457
-
458
- const maybeAbort = () => {
459
- if (
460
- chunkDeferred.size === 0 &&
461
- Array.from(controllers.values()).every((it) => it.returned)
462
- ) {
463
- // nothing is listening to the stream anymore
464
- opts.abortController?.abort();
465
- }
466
- };
538
+ const streamManager = createStreamsManager(opts.abortController);
467
539
 
468
- function hydrateChunkDefinition(value: ChunkDefinition) {
540
+ function decodeChunkDefinition(value: ChunkDefinition) {
469
541
  const [_path, type, chunkId] = value;
470
542
 
471
- const { readable, controller } = createReadableStream<ChunkData>();
472
-
473
- const wrapper: ControllerWrapper = {
474
- controller,
475
- returned: false,
476
- };
477
- controllers.set(chunkId, wrapper);
478
-
479
- // resolve chunk deferred if it exists
480
- const deferred = chunkDeferred.get(chunkId);
481
- if (deferred) {
482
- deferred.resolve(wrapper);
483
- chunkDeferred.delete(chunkId);
484
- }
543
+ const controller = streamManager.getOrCreate(chunkId);
485
544
 
486
545
  switch (type) {
487
546
  case CHUNK_VALUE_TYPE_PROMISE: {
488
- return new Promise((resolve, reject) => {
489
- // listen for next value in the stream
490
- const reader = readable.getReader();
491
- reader
492
- .read()
493
- .then((it) => {
494
- if (it.done) {
495
- reject(new Error('Promise chunk ended without value'));
496
- return;
497
- }
498
- if (it.value instanceof StreamInterruptedError) {
499
- reject(it.value);
500
- return;
501
- }
502
- const value = it.value;
503
- const [_chunkId, status, data] = value as PromiseChunk;
504
- switch (status) {
505
- case PROMISE_STATUS_FULFILLED:
506
- resolve(hydrate(data));
507
-
508
- break;
509
- case PROMISE_STATUS_REJECTED:
510
- reject(
511
- opts.formatError?.({ error: data }) ?? new AsyncError(data),
512
- );
513
- break;
514
- }
515
- })
516
- .catch(reject)
517
- .finally(() => {
518
- // reader.releaseLock();
519
- controllers.delete(chunkId);
520
-
521
- maybeAbort();
522
- });
547
+ return run(async () => {
548
+ using reader = controller.getReaderResource();
549
+
550
+ const { value } = await reader.read();
551
+ if (value instanceof StreamInterruptedError) {
552
+ throw value;
553
+ }
554
+ const [_chunkId, status, data] = value as PromiseChunk;
555
+ switch (status) {
556
+ case PROMISE_STATUS_FULFILLED:
557
+ return decode(data);
558
+ case PROMISE_STATUS_REJECTED:
559
+ throw opts.formatError?.({ error: data }) ?? new AsyncError(data);
560
+ }
523
561
  });
524
562
  }
525
563
  case CHUNK_VALUE_TYPE_ASYNC_ITERABLE: {
526
- return {
527
- [Symbol.asyncIterator]: () => {
528
- const reader = readable.getReader();
529
- const iterator: AsyncIterator<unknown> = {
530
- next: async () => {
531
- const { done, value } = await reader.read();
532
- if (value instanceof StreamInterruptedError) {
533
- throw value;
534
- }
535
- if (done) {
536
- controllers.delete(chunkId);
537
- maybeAbort();
538
- return {
539
- done: true,
540
- value: undefined,
541
- };
542
- }
543
-
544
- const [_chunkId, status, data] = value as IterableChunk;
545
-
546
- switch (status) {
547
- case ASYNC_ITERABLE_STATUS_VALUE:
548
- return {
549
- done: false,
550
- value: hydrate(data),
551
- };
552
- case ASYNC_ITERABLE_STATUS_RETURN:
553
- controllers.delete(chunkId);
554
- maybeAbort();
555
- return {
556
- done: true,
557
- value: hydrate(data),
558
- };
559
- case ASYNC_ITERABLE_STATUS_ERROR:
560
- controllers.delete(chunkId);
561
- maybeAbort();
562
- throw (
563
- opts.formatError?.({ error: data }) ??
564
- new AsyncError(data)
565
- );
566
- }
567
- },
568
- return: async () => {
569
- wrapper.returned = true;
570
- maybeAbort();
571
- return {
572
- done: true,
573
- value: undefined,
574
- };
575
- },
576
- };
577
- return iterator;
578
- },
579
- };
564
+ return run(async function* () {
565
+ using reader = controller.getReaderResource();
566
+
567
+ while (true) {
568
+ const { value } = await reader.read();
569
+ if (value instanceof StreamInterruptedError) {
570
+ throw value;
571
+ }
572
+
573
+ const [_chunkId, status, data] = value as IterableChunk;
574
+
575
+ switch (status) {
576
+ case ASYNC_ITERABLE_STATUS_YIELD:
577
+ yield decode(data);
578
+ break;
579
+ case ASYNC_ITERABLE_STATUS_RETURN:
580
+ return decode(data);
581
+ case ASYNC_ITERABLE_STATUS_ERROR:
582
+ throw (
583
+ opts.formatError?.({ error: data }) ?? new AsyncError(data)
584
+ );
585
+ }
586
+ }
587
+ });
580
588
  }
581
589
  }
582
590
  }
583
591
 
584
- function hydrate(value: DehydratedValue): unknown {
592
+ function decode(value: EncodedValue): unknown {
585
593
  const [[data], ...asyncProps] = value;
586
594
 
587
595
  for (const value of asyncProps) {
588
596
  const [key] = value;
589
- const hydrated = hydrateChunkDefinition(value);
597
+ const decoded = decodeChunkDefinition(value);
590
598
 
591
599
  if (key === null) {
592
- return hydrated;
600
+ return decoded;
593
601
  }
594
602
 
595
- (data as any)[key] = hydrated;
603
+ (data as any)[key] = decoded;
596
604
  }
597
605
  return data;
598
606
  }
@@ -601,58 +609,41 @@ export async function jsonlStreamConsumer<THead>(opts: {
601
609
  const error = new StreamInterruptedError(reason);
602
610
 
603
611
  headDeferred?.reject(error);
604
- for (const deferred of chunkDeferred.values()) {
605
- deferred.reject(error);
606
- }
607
- chunkDeferred.clear();
608
- for (const { controller } of controllers.values()) {
609
- controller.enqueue(error);
610
- controller.close();
611
- }
612
- controllers.clear();
612
+ streamManager.cancelAll(error);
613
613
  };
614
614
  source
615
615
  .pipeTo(
616
616
  new WritableStream({
617
- async write(chunkOrHead) {
617
+ write(chunkOrHead) {
618
618
  if (headDeferred) {
619
619
  const head = chunkOrHead as Record<number | string, unknown>;
620
620
 
621
621
  for (const [key, value] of Object.entries(chunkOrHead)) {
622
- const parsed = hydrate(value as any);
622
+ const parsed = decode(value as any);
623
623
  head[key] = parsed;
624
624
  }
625
625
  headDeferred.resolve(head as THead);
626
626
  headDeferred = null;
627
+
627
628
  return;
628
629
  }
629
630
  const chunk = chunkOrHead as ChunkData;
630
631
  const [idx] = chunk;
631
- let wrapper = controllers.get(idx);
632
- if (!wrapper) {
633
- let deferred = chunkDeferred.get(idx);
634
- if (!deferred) {
635
- deferred = createDeferred();
636
- chunkDeferred.set(idx, deferred);
637
- }
638
632
 
639
- wrapper = await deferred.promise;
640
- }
641
- wrapper.controller.enqueue(chunk);
633
+ const controller = streamManager.getOrCreate(idx);
634
+ controller.enqueue(chunk);
642
635
  },
643
636
  close: closeOrAbort,
644
637
  abort: closeOrAbort,
645
638
  }),
639
+ {
640
+ signal: opts.abortController.signal,
641
+ },
646
642
  )
647
643
  .catch((error) => {
648
644
  opts.onError?.({ error });
649
645
  closeOrAbort(error);
650
646
  });
651
647
 
652
- return [
653
- await headDeferred.promise,
654
- {
655
- controllers,
656
- },
657
- ] as const;
648
+ return [await headDeferred.promise, streamManager] as const;
658
649
  }