@trpc/server 11.0.0-alpha-tmp-subscription-connection-state.488 → 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 (276) 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 +5 -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 +236 -90
  55. package/dist/adapters/ws.mjs +237 -92
  56. package/dist/bundle-analysis.json +411 -294
  57. package/dist/http.js +2 -4
  58. package/dist/http.mjs +2 -2
  59. package/dist/index.js +6 -2
  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 +187 -92
  107. package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +189 -94
  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 +32 -13
  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 +11 -6
  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.d.ts.map +1 -1
  138. package/dist/unstable-core-do-not-import/rpc/parseTRPCMessage.js +7 -3
  139. package/dist/unstable-core-do-not-import/rpc/parseTRPCMessage.mjs +7 -3
  140. package/dist/unstable-core-do-not-import/stream/jsonl.d.ts +31 -16
  141. package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -1
  142. package/dist/unstable-core-do-not-import/stream/jsonl.js +440 -318
  143. package/dist/unstable-core-do-not-import/stream/jsonl.mjs +440 -318
  144. package/dist/unstable-core-do-not-import/stream/sse.d.ts +63 -41
  145. package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
  146. package/dist/unstable-core-do-not-import/stream/sse.js +300 -119
  147. package/dist/unstable-core-do-not-import/stream/sse.mjs +302 -119
  148. package/dist/unstable-core-do-not-import/stream/sse.types.d.ts +31 -0
  149. package/dist/unstable-core-do-not-import/stream/sse.types.d.ts.map +1 -0
  150. package/dist/unstable-core-do-not-import/stream/tracked.d.ts +31 -0
  151. package/dist/unstable-core-do-not-import/stream/tracked.d.ts.map +1 -0
  152. package/dist/unstable-core-do-not-import/stream/tracked.js +29 -0
  153. package/dist/unstable-core-do-not-import/stream/tracked.mjs +25 -0
  154. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts +17 -0
  155. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts.map +1 -0
  156. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.js +171 -0
  157. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.mjs +167 -0
  158. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts +0 -11
  159. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts.map +1 -1
  160. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.js +0 -29
  161. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.mjs +1 -29
  162. package/dist/unstable-core-do-not-import/stream/utils/disposable.d.ts +17 -0
  163. package/dist/unstable-core-do-not-import/stream/utils/disposable.d.ts.map +1 -0
  164. package/dist/unstable-core-do-not-import/stream/utils/disposable.js +44 -0
  165. package/dist/unstable-core-do-not-import/stream/utils/disposable.mjs +41 -0
  166. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.d.ts +8 -0
  167. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.d.ts.map +1 -0
  168. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.js +25 -0
  169. package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.mjs +23 -0
  170. package/dist/unstable-core-do-not-import/stream/utils/timerResource.d.ts +5 -0
  171. package/dist/unstable-core-do-not-import/stream/utils/timerResource.d.ts.map +1 -0
  172. package/dist/unstable-core-do-not-import/stream/utils/timerResource.js +26 -0
  173. package/dist/unstable-core-do-not-import/stream/utils/timerResource.mjs +23 -0
  174. package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts +7 -0
  175. package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts.map +1 -0
  176. package/dist/unstable-core-do-not-import/stream/utils/withPing.js +130 -0
  177. package/dist/unstable-core-do-not-import/stream/utils/withPing.mjs +127 -0
  178. package/dist/unstable-core-do-not-import/transformer.d.ts +2 -4
  179. package/dist/unstable-core-do-not-import/transformer.d.ts.map +1 -1
  180. package/dist/unstable-core-do-not-import/transformer.js +1 -1
  181. package/dist/unstable-core-do-not-import/transformer.mjs +1 -1
  182. package/dist/unstable-core-do-not-import/types.d.ts +26 -3
  183. package/dist/unstable-core-do-not-import/types.d.ts.map +1 -1
  184. package/dist/unstable-core-do-not-import/utils.d.ts +15 -0
  185. package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
  186. package/dist/unstable-core-do-not-import/utils.js +49 -1
  187. package/dist/unstable-core-do-not-import/utils.mjs +45 -2
  188. package/dist/unstable-core-do-not-import.d.ts +4 -2
  189. package/dist/unstable-core-do-not-import.d.ts.map +1 -1
  190. package/dist/unstable-core-do-not-import.js +18 -9
  191. package/dist/unstable-core-do-not-import.mjs +7 -7
  192. package/dist/vendor/unpromise/index.d.ts +3 -0
  193. package/dist/vendor/unpromise/index.d.ts.map +1 -0
  194. package/dist/vendor/unpromise/types.d.ts +28 -0
  195. package/dist/vendor/unpromise/types.d.ts.map +1 -0
  196. package/dist/vendor/unpromise/unpromise.d.ts +121 -0
  197. package/dist/vendor/unpromise/unpromise.d.ts.map +1 -0
  198. package/dist/vendor/unpromise/unpromise.js +292 -0
  199. package/dist/vendor/unpromise/unpromise.mjs +289 -0
  200. package/package.json +20 -17
  201. package/src/@trpc/server/http.ts +0 -2
  202. package/src/@trpc/server/index.ts +6 -0
  203. package/src/adapters/aws-lambda/getPlanner.ts +2 -2
  204. package/src/adapters/aws-lambda/index.ts +5 -6
  205. package/src/adapters/express.ts +21 -9
  206. package/src/adapters/fastify/fastifyRequestHandler.ts +1 -1
  207. package/src/adapters/fastify/fastifyTRPCPlugin.ts +16 -5
  208. package/src/adapters/fetch/fetchRequestHandler.ts +2 -2
  209. package/src/adapters/next-app-dir/nextAppDirCaller.ts +3 -0
  210. package/src/adapters/next-app-dir/rethrowNextErrors.ts +3 -2
  211. package/src/adapters/next.ts +29 -34
  212. package/src/adapters/node-http/incomingMessageToRequest.ts +110 -40
  213. package/src/adapters/node-http/nodeHTTPRequestHandler.ts +85 -63
  214. package/src/adapters/node-http/writeResponse.ts +94 -0
  215. package/src/adapters/standalone.ts +35 -18
  216. package/src/adapters/ws.ts +152 -62
  217. package/src/observable/behaviorSubject.ts +55 -0
  218. package/src/observable/index.ts +22 -3
  219. package/src/observable/observable.ts +32 -14
  220. package/src/observable/operators.ts +47 -0
  221. package/src/unstable-core-do-not-import/clientish/inference.ts +4 -4
  222. package/src/unstable-core-do-not-import/clientish/inferrable.ts +6 -6
  223. package/src/unstable-core-do-not-import/clientish/serialize.ts +5 -5
  224. package/src/unstable-core-do-not-import/http/getHTTPStatusCode.ts +37 -4
  225. package/src/unstable-core-do-not-import/http/isAbortError.ts +7 -0
  226. package/src/unstable-core-do-not-import/http/resolveResponse.ts +192 -85
  227. package/src/unstable-core-do-not-import/http/types.ts +1 -1
  228. package/src/unstable-core-do-not-import/initTRPC.ts +14 -20
  229. package/src/unstable-core-do-not-import/middleware.ts +5 -4
  230. package/src/unstable-core-do-not-import/parser.ts +17 -6
  231. package/src/unstable-core-do-not-import/procedure.ts +17 -2
  232. package/src/unstable-core-do-not-import/procedureBuilder.ts +138 -123
  233. package/src/unstable-core-do-not-import/rootConfig.ts +20 -17
  234. package/src/unstable-core-do-not-import/router.ts +15 -16
  235. package/src/unstable-core-do-not-import/rpc/codes.ts +2 -10
  236. package/src/unstable-core-do-not-import/rpc/envelopes.ts +18 -7
  237. package/src/unstable-core-do-not-import/rpc/parseTRPCMessage.ts +5 -1
  238. package/src/unstable-core-do-not-import/stream/jsonl.ts +293 -294
  239. package/src/unstable-core-do-not-import/stream/sse.ts +349 -191
  240. package/src/unstable-core-do-not-import/stream/sse.types.ts +44 -0
  241. package/src/unstable-core-do-not-import/stream/tracked.ts +49 -0
  242. package/src/unstable-core-do-not-import/stream/utils/asyncIterable.ts +89 -0
  243. package/src/unstable-core-do-not-import/stream/utils/createDeferred.ts +0 -36
  244. package/src/unstable-core-do-not-import/stream/utils/disposable.ts +52 -0
  245. package/src/unstable-core-do-not-import/stream/utils/readableStreamFrom.ts +28 -0
  246. package/src/unstable-core-do-not-import/stream/utils/timerResource.ts +29 -0
  247. package/src/unstable-core-do-not-import/stream/utils/withPing.ts +47 -0
  248. package/src/unstable-core-do-not-import/transformer.ts +1 -1
  249. package/src/unstable-core-do-not-import/types.ts +35 -10
  250. package/src/unstable-core-do-not-import/utils.ts +56 -1
  251. package/src/unstable-core-do-not-import.ts +4 -2
  252. package/src/vendor/unpromise/ATTRIBUTION.txt +1 -0
  253. package/src/vendor/unpromise/LICENSE +20 -0
  254. package/src/vendor/unpromise/index.ts +7 -0
  255. package/src/vendor/unpromise/types.ts +55 -0
  256. package/src/vendor/unpromise/unpromise.ts +380 -0
  257. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.d.ts +0 -24
  258. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.d.ts.map +0 -1
  259. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.js +0 -32
  260. package/dist/unstable-core-do-not-import/http/batchStreamFormatter.mjs +0 -30
  261. package/dist/unstable-core-do-not-import/http/toURL.d.ts +0 -2
  262. package/dist/unstable-core-do-not-import/http/toURL.d.ts.map +0 -1
  263. package/dist/unstable-core-do-not-import/http/toURL.js +0 -8
  264. package/dist/unstable-core-do-not-import/http/toURL.mjs +0 -6
  265. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts +0 -10
  266. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts.map +0 -1
  267. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.js +0 -31
  268. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.mjs +0 -29
  269. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts +0 -7
  270. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts.map +0 -1
  271. package/dist/unstable-core-do-not-import/types.js +0 -11
  272. package/dist/unstable-core-do-not-import/types.mjs +0 -9
  273. package/src/unstable-core-do-not-import/http/batchStreamFormatter.ts +0 -29
  274. package/src/unstable-core-do-not-import/http/toURL.ts +0 -7
  275. package/src/unstable-core-do-not-import/stream/utils/createReadableStream.ts +0 -31
  276. 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;
@@ -30,10 +34,10 @@ type PROMISE_STATUS_FULFILLED = typeof PROMISE_STATUS_FULFILLED;
30
34
  const PROMISE_STATUS_REJECTED = 1;
31
35
  type PROMISE_STATUS_REJECTED = typeof PROMISE_STATUS_REJECTED;
32
36
 
33
- const ASYNC_ITERABLE_STATUS_DONE = 0;
34
- type ASYNC_ITERABLE_STATUS_DONE = typeof ASYNC_ITERABLE_STATUS_DONE;
35
- const ASYNC_ITERABLE_STATUS_VALUE = 1;
36
- type ASYNC_ITERABLE_STATUS_VALUE = typeof ASYNC_ITERABLE_STATUS_VALUE;
37
+ const ASYNC_ITERABLE_STATUS_RETURN = 0;
38
+ type ASYNC_ITERABLE_STATUS_RETURN = typeof ASYNC_ITERABLE_STATUS_RETURN;
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,27 +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
- | [chunkIndex: ChunkIndex, status: ASYNC_ITERABLE_STATUS_DONE]
74
77
  | [
75
78
  chunkIndex: ChunkIndex,
76
- status: ASYNC_ITERABLE_STATUS_VALUE,
77
- value: DehydratedValue,
79
+ status: ASYNC_ITERABLE_STATUS_RETURN,
80
+ value: EncodedValue,
81
+ ]
82
+ | [
83
+ chunkIndex: ChunkIndex,
84
+ status: ASYNC_ITERABLE_STATUS_YIELD,
85
+ value: EncodedValue,
78
86
  ]
79
87
  | [
80
88
  chunkIndex: ChunkIndex,
@@ -113,124 +121,98 @@ class MaxDepthError extends Error {
113
121
  }
114
122
  }
115
123
 
116
- function createBatchStreamProducer(opts: ProducerOptions) {
124
+ async function* createBatchStreamProducer(
125
+ opts: ProducerOptions,
126
+ ): AsyncIterable<Head | ChunkData, void> {
117
127
  const { data } = opts;
118
128
  let counter = 0 as ChunkIndex;
119
129
  const placeholder = 0 as PlaceholderValue;
120
130
 
121
- const stream = createReadableStream<ChunkData>();
122
- const pending = new Set<ChunkIndex>();
123
-
124
- function maybeClose() {
125
- if (pending.size === 0 && !stream.cancelled()) {
126
- stream.controller.close();
127
- }
128
- }
129
- function dehydratePromise(
130
- promise: Promise<unknown>,
131
- 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>,
132
142
  ) {
133
- //
134
- const error = checkMaxDepth(path);
135
- if (error) {
136
- promise.catch(() => {
137
- // ignore
138
- });
139
- promise = Promise.reject(error);
140
- }
141
143
  const idx = counter++ as ChunkIndex;
142
- pending.add(idx);
143
144
 
144
- Promise.race([promise, stream.cancelledPromise])
145
- .then((it) => {
146
- if (it === null) {
147
- return;
148
- }
149
- stream.controller.enqueue([
150
- idx,
151
- PROMISE_STATUS_FULFILLED,
152
- dehydrate(it, path),
153
- ]);
154
- })
155
- .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) {
156
175
  opts.onError?.({ error: cause, path });
157
- stream.controller.enqueue([
176
+ return [
158
177
  idx,
159
178
  PROMISE_STATUS_REJECTED,
160
179
  opts.formatError?.({ error: cause, path }),
161
- ]);
162
- })
163
- .finally(() => {
164
- pending.delete(idx);
165
- maybeClose();
166
- });
167
- return idx;
180
+ ];
181
+ }
182
+ });
168
183
  }
169
- function dehydrateAsyncIterable(
184
+ function encodeAsyncIterable(
170
185
  iterable: AsyncIterable<unknown>,
171
186
  path: (string | number)[],
172
187
  ) {
173
- const error = checkMaxDepth(path);
174
- if (error) {
175
- iterable = {
176
- [Symbol.asyncIterator]() {
177
- throw error;
178
- },
179
- };
180
- }
181
- const idx = counter++ as ChunkIndex;
182
- pending.add(idx);
183
- run(async () => {
184
- const iterator = iterable[Symbol.asyncIterator]();
185
-
186
- while (true) {
187
- const next = await Promise.race([
188
- iterator.next().catch(getTRPCErrorFromUnknown),
189
- stream.cancelledPromise,
190
- ]);
191
-
192
- if (next instanceof Error) {
193
- opts.onError?.({ error: next, path });
194
-
195
- stream.controller.enqueue([
196
- idx,
197
- ASYNC_ITERABLE_STATUS_ERROR,
198
- opts.formatError?.({ error: next, path }),
199
- ]);
200
- return;
201
- }
202
- if (next === 'cancelled') {
203
- await iterator.return?.();
204
- break;
205
- }
206
- if (next.done) {
207
- stream.controller.enqueue([idx, ASYNC_ITERABLE_STATUS_DONE]);
208
- 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)];
209
206
  }
210
- stream.controller.enqueue([
207
+ } catch (cause) {
208
+ opts.onError?.({ error: cause, path });
209
+ return [
211
210
  idx,
212
- ASYNC_ITERABLE_STATUS_VALUE,
213
- dehydrate(next.value, path),
214
- ]);
211
+ ASYNC_ITERABLE_STATUS_ERROR,
212
+ opts.formatError?.({ error: cause, path }),
213
+ ];
215
214
  }
216
-
217
- pending.delete(idx);
218
- maybeClose();
219
- }).catch((cause) => {
220
- // this shouldn't happen, but node crashes if we don't catch it
221
- opts.onError?.({
222
- error: new Error(
223
- 'You found a bug - please report it on https://github.com/trpc/trpc',
224
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
225
- // @ts-ignore https://github.com/tc39/proposal-error-cause
226
- {
227
- cause,
228
- },
229
- ),
230
- path,
231
- });
232
215
  });
233
- return idx;
234
216
  }
235
217
  function checkMaxDepth(path: (string | number)[]) {
236
218
  if (opts.maxDepth && path.length > opts.maxDepth) {
@@ -238,12 +220,12 @@ function createBatchStreamProducer(opts: ProducerOptions) {
238
220
  }
239
221
  return null;
240
222
  }
241
- function dehydrateChunk(
223
+ function encodeAsync(
242
224
  value: unknown,
243
225
  path: (string | number)[],
244
226
  ): null | [type: ChunkValueType, chunkId: ChunkIndex] {
245
227
  if (isPromise(value)) {
246
- return [CHUNK_VALUE_TYPE_PROMISE, dehydratePromise(value, path)];
228
+ return [CHUNK_VALUE_TYPE_PROMISE, encodePromise(value, path)];
247
229
  }
248
230
  if (isAsyncIterable(value)) {
249
231
  if (opts.maxDepth && path.length >= opts.maxDepth) {
@@ -251,26 +233,26 @@ function createBatchStreamProducer(opts: ProducerOptions) {
251
233
  }
252
234
  return [
253
235
  CHUNK_VALUE_TYPE_ASYNC_ITERABLE,
254
- dehydrateAsyncIterable(value, path),
236
+ encodeAsyncIterable(value, path),
255
237
  ];
256
238
  }
257
239
  return null;
258
240
  }
259
- function dehydrate(
260
- value: unknown,
261
- path: (string | number)[],
262
- ): DehydratedValue {
263
- const reg = dehydrateChunk(value, path);
264
- if (reg) {
265
- return [[placeholder], [null, ...reg]];
241
+ function encode(value: unknown, path: (string | number)[]): EncodedValue {
242
+ if (value === undefined) {
243
+ return [[]];
266
244
  }
267
245
  if (!isObject(value)) {
268
246
  return [[value]];
269
247
  }
248
+ const reg = encodeAsync(value, path);
249
+ if (reg) {
250
+ return [[placeholder], [null, ...reg]];
251
+ }
270
252
  const newObj = {} as Record<string, unknown>;
271
253
  const asyncValues: ChunkDefinition[] = [];
272
254
  for (const [key, item] of Object.entries(value)) {
273
- const transformed = dehydrateChunk(item, [...path, key]);
255
+ const transformed = encodeAsync(item, [...path, key]);
274
256
  if (!transformed) {
275
257
  newObj[key] = item;
276
258
  continue;
@@ -283,21 +265,37 @@ function createBatchStreamProducer(opts: ProducerOptions) {
283
265
 
284
266
  const newHead: Head = {};
285
267
  for (const [key, item] of Object.entries(data)) {
286
- newHead[key] = dehydrate(item, [key]);
268
+ newHead[key] = encode(item, [key]);
287
269
  }
288
270
 
289
- 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
+ }
290
289
  }
291
290
  /**
292
291
  * JSON Lines stream producer
293
292
  * @see https://jsonlines.org/
294
293
  */
295
294
  export function jsonlStreamProducer(opts: ProducerOptions) {
296
- let [head, stream] = createBatchStreamProducer(opts);
295
+ let stream = readableStreamFrom(createBatchStreamProducer(opts));
297
296
 
298
297
  const { serialize } = opts;
299
298
  if (serialize) {
300
- head = serialize(head);
301
299
  stream = stream.pipeThrough(
302
300
  new TransformStream({
303
301
  transform(chunk, controller) {
@@ -310,9 +308,6 @@ export function jsonlStreamProducer(opts: ProducerOptions) {
310
308
  return stream
311
309
  .pipeThrough(
312
310
  new TransformStream({
313
- start(controller) {
314
- controller.enqueue(JSON.stringify(head) + '\n');
315
- },
316
311
  transform(chunk, controller) {
317
312
  controller.enqueue(JSON.stringify(chunk) + '\n');
318
313
  },
@@ -338,17 +333,20 @@ export type ConsumerOnError = (opts: { error: unknown }) => void;
338
333
  const nodeJsStreamToReaderEsque = (source: NodeJSReadableStreamEsque) => {
339
334
  return {
340
335
  getReader() {
341
- const { readable, controller } = createReadableStream<Uint8Array>();
342
- source.on('data', (chunk) => {
343
- controller.enqueue(chunk);
344
- });
345
- source.on('end', () => {
346
- controller.close();
347
- });
348
- source.on('error', (error) => {
349
- 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
+ },
350
348
  });
351
- return readable.getReader();
349
+ return stream.getReader();
352
350
  },
353
351
  };
354
352
  };
@@ -412,6 +410,102 @@ function createConsumerStream<THead>(
412
410
  }),
413
411
  );
414
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
+ }
415
509
 
416
510
  /**
417
511
  * JSON Lines stream consumer
@@ -422,7 +516,10 @@ export async function jsonlStreamConsumer<THead>(opts: {
422
516
  deserialize?: Deserialize;
423
517
  onError?: ConsumerOnError;
424
518
  formatError?: (opts: { error: unknown }) => Error;
425
- abortController: AbortController | null;
519
+ /**
520
+ * This `AbortController` will be triggered when there are no more listeners to the stream.
521
+ */
522
+ abortController: AbortController;
426
523
  }) {
427
524
  const { deserialize = (v) => v } = opts;
428
525
 
@@ -438,153 +535,72 @@ export async function jsonlStreamConsumer<THead>(opts: {
438
535
  }
439
536
  let headDeferred: null | Deferred<THead> = createDeferred();
440
537
 
441
- type ControllerChunk = ChunkData | StreamInterruptedError;
442
- type ChunkController = ReadableStreamDefaultController<ControllerChunk>;
443
- type ControllerWrapper = {
444
- controller: ChunkController;
445
- returned: boolean;
446
- };
447
- const chunkDeferred = new Map<ChunkIndex, Deferred<ControllerWrapper>>();
448
- const controllers = new Map<ChunkIndex, ControllerWrapper>();
449
-
450
- const maybeAbort = () => {
451
- if (
452
- chunkDeferred.size === 0 &&
453
- Array.from(controllers.values()).every((it) => it.returned)
454
- ) {
455
- // nothing is listening to the stream anymore
456
- opts.abortController?.abort();
457
- }
458
- };
538
+ const streamManager = createStreamsManager(opts.abortController);
459
539
 
460
- function hydrateChunkDefinition(value: ChunkDefinition) {
540
+ function decodeChunkDefinition(value: ChunkDefinition) {
461
541
  const [_path, type, chunkId] = value;
462
542
 
463
- const { readable, controller } = createReadableStream<ChunkData>();
464
-
465
- const wrapper: ControllerWrapper = {
466
- controller,
467
- returned: false,
468
- };
469
- controllers.set(chunkId, wrapper);
470
-
471
- // resolve chunk deferred if it exists
472
- const deferred = chunkDeferred.get(chunkId);
473
- if (deferred) {
474
- deferred.resolve(wrapper);
475
- chunkDeferred.delete(chunkId);
476
- }
543
+ const controller = streamManager.getOrCreate(chunkId);
477
544
 
478
545
  switch (type) {
479
546
  case CHUNK_VALUE_TYPE_PROMISE: {
480
- return new Promise((resolve, reject) => {
481
- // listen for next value in the stream
482
- const reader = readable.getReader();
483
- reader
484
- .read()
485
- .then((it) => {
486
- if (it.done) {
487
- reject(new Error('Promise chunk ended without value'));
488
- return;
489
- }
490
- if (it.value instanceof StreamInterruptedError) {
491
- reject(it.value);
492
- return;
493
- }
494
- const value = it.value;
495
- const [_chunkId, status, data] = value as PromiseChunk;
496
- switch (status) {
497
- case PROMISE_STATUS_FULFILLED:
498
- resolve(hydrate(data));
499
-
500
- break;
501
- case PROMISE_STATUS_REJECTED:
502
- reject(
503
- opts.formatError?.({ error: data }) ?? new AsyncError(data),
504
- );
505
- break;
506
- }
507
- })
508
- .catch(reject)
509
- .finally(() => {
510
- // reader.releaseLock();
511
- controllers.delete(chunkId);
512
-
513
- maybeAbort();
514
- });
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
+ }
515
561
  });
516
562
  }
517
563
  case CHUNK_VALUE_TYPE_ASYNC_ITERABLE: {
518
- return {
519
- [Symbol.asyncIterator]: () => {
520
- const reader = readable.getReader();
521
- const iterator: AsyncIterator<unknown> = {
522
- next: async () => {
523
- const { done, value } = await reader.read();
524
- if (value instanceof StreamInterruptedError) {
525
- throw value;
526
- }
527
- if (done) {
528
- controllers.delete(chunkId);
529
- maybeAbort();
530
- return {
531
- done: true,
532
- value: undefined,
533
- };
534
- }
535
-
536
- const [_chunkId, status, data] = value as IterableChunk;
537
-
538
- switch (status) {
539
- case ASYNC_ITERABLE_STATUS_VALUE:
540
- return {
541
- done: false,
542
- value: hydrate(data),
543
- };
544
- case ASYNC_ITERABLE_STATUS_DONE:
545
- controllers.delete(chunkId);
546
- maybeAbort();
547
- return {
548
- done: true,
549
- value: undefined,
550
- };
551
- case ASYNC_ITERABLE_STATUS_ERROR:
552
- controllers.delete(chunkId);
553
- maybeAbort();
554
- throw (
555
- opts.formatError?.({ error: data }) ??
556
- new AsyncError(data)
557
- );
558
- }
559
- },
560
- return: async () => {
561
- wrapper.returned = true;
562
- maybeAbort();
563
- return {
564
- done: true,
565
- value: undefined,
566
- };
567
- },
568
- };
569
- return iterator;
570
- },
571
- };
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
+ });
572
588
  }
573
589
  }
574
590
  }
575
591
 
576
- function hydrate(value: DehydratedValue): unknown {
592
+ function decode(value: EncodedValue): unknown {
577
593
  const [[data], ...asyncProps] = value;
578
594
 
579
595
  for (const value of asyncProps) {
580
596
  const [key] = value;
581
- const hydrated = hydrateChunkDefinition(value);
597
+ const decoded = decodeChunkDefinition(value);
582
598
 
583
599
  if (key === null) {
584
- return hydrated;
600
+ return decoded;
585
601
  }
586
602
 
587
- (data as any)[key] = hydrated;
603
+ (data as any)[key] = decoded;
588
604
  }
589
605
  return data;
590
606
  }
@@ -593,58 +609,41 @@ export async function jsonlStreamConsumer<THead>(opts: {
593
609
  const error = new StreamInterruptedError(reason);
594
610
 
595
611
  headDeferred?.reject(error);
596
- for (const deferred of chunkDeferred.values()) {
597
- deferred.reject(error);
598
- }
599
- chunkDeferred.clear();
600
- for (const { controller } of controllers.values()) {
601
- controller.enqueue(error);
602
- controller.close();
603
- }
604
- controllers.clear();
612
+ streamManager.cancelAll(error);
605
613
  };
606
614
  source
607
615
  .pipeTo(
608
616
  new WritableStream({
609
- async write(chunkOrHead) {
617
+ write(chunkOrHead) {
610
618
  if (headDeferred) {
611
619
  const head = chunkOrHead as Record<number | string, unknown>;
612
620
 
613
621
  for (const [key, value] of Object.entries(chunkOrHead)) {
614
- const parsed = hydrate(value as any);
622
+ const parsed = decode(value as any);
615
623
  head[key] = parsed;
616
624
  }
617
625
  headDeferred.resolve(head as THead);
618
626
  headDeferred = null;
627
+
619
628
  return;
620
629
  }
621
630
  const chunk = chunkOrHead as ChunkData;
622
631
  const [idx] = chunk;
623
- let wrapper = controllers.get(idx);
624
- if (!wrapper) {
625
- let deferred = chunkDeferred.get(idx);
626
- if (!deferred) {
627
- deferred = createDeferred();
628
- chunkDeferred.set(idx, deferred);
629
- }
630
632
 
631
- wrapper = await deferred.promise;
632
- }
633
- wrapper.controller.enqueue(chunk);
633
+ const controller = streamManager.getOrCreate(idx);
634
+ controller.enqueue(chunk);
634
635
  },
635
636
  close: closeOrAbort,
636
637
  abort: closeOrAbort,
637
638
  }),
639
+ {
640
+ signal: opts.abortController.signal,
641
+ },
638
642
  )
639
643
  .catch((error) => {
640
644
  opts.onError?.({ error });
641
645
  closeOrAbort(error);
642
646
  });
643
647
 
644
- return [
645
- await headDeferred.promise,
646
- {
647
- controllers,
648
- },
649
- ] as const;
648
+ return [await headDeferred.promise, streamManager] as const;
650
649
  }