@cj-tech-master/excelts 4.2.1 → 4.2.2-canary.20260115044841.88820eb

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 (331) hide show
  1. package/THIRD_PARTY_NOTICES.md +0 -31
  2. package/dist/browser/index.browser.d.ts +1 -0
  3. package/dist/browser/index.browser.js +12 -0
  4. package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.base.js +1 -1
  5. package/dist/{types/modules/archive → browser/modules/archive/compression}/compress.browser.d.ts +2 -8
  6. package/dist/browser/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
  7. package/dist/browser/modules/archive/{compress.d.ts → compression/compress.d.ts} +2 -2
  8. package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.js +1 -1
  9. package/dist/browser/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +1 -1
  10. package/dist/browser/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +1 -1
  11. package/dist/browser/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  12. package/dist/browser/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  13. package/dist/browser/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +2 -2
  14. package/dist/browser/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  15. package/dist/browser/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +2 -2
  16. package/dist/browser/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  17. package/dist/browser/modules/archive/defaults.d.ts +1 -0
  18. package/dist/browser/modules/archive/defaults.js +6 -3
  19. package/dist/browser/modules/archive/index.base.d.ts +4 -4
  20. package/dist/browser/modules/archive/index.base.js +3 -6
  21. package/dist/browser/modules/archive/index.browser.d.ts +3 -4
  22. package/dist/browser/modules/archive/index.browser.js +3 -7
  23. package/dist/browser/modules/archive/index.d.ts +3 -4
  24. package/dist/browser/modules/archive/index.js +3 -5
  25. package/dist/browser/modules/archive/internal/byte-queue.d.ts +33 -0
  26. package/dist/browser/modules/archive/internal/byte-queue.js +407 -0
  27. package/dist/browser/modules/archive/io/archive-sink.d.ts +8 -0
  28. package/dist/browser/modules/archive/io/archive-sink.js +45 -0
  29. package/dist/browser/modules/archive/io/archive-source.d.ts +6 -0
  30. package/dist/browser/modules/archive/io/archive-source.js +100 -0
  31. package/dist/browser/modules/archive/{extract.d.ts → unzip/extract.d.ts} +2 -2
  32. package/dist/browser/modules/archive/unzip/index.d.ts +40 -0
  33. package/dist/browser/modules/archive/unzip/index.js +164 -0
  34. package/dist/browser/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +36 -2
  35. package/dist/browser/modules/archive/unzip/stream.base.js +1022 -0
  36. package/dist/browser/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +1 -1
  37. package/dist/browser/modules/archive/{parse.browser.js → unzip/stream.browser.js} +371 -110
  38. package/dist/browser/modules/archive/{parse.d.ts → unzip/stream.d.ts} +2 -2
  39. package/dist/{esm/modules/archive/parse.js → browser/modules/archive/unzip/stream.js} +6 -5
  40. package/dist/browser/modules/archive/{zip-parser.d.ts → unzip/zip-parser.d.ts} +1 -1
  41. package/dist/{esm/modules/archive → browser/modules/archive/unzip}/zip-parser.js +38 -24
  42. package/dist/browser/modules/archive/utils/async-queue.d.ts +7 -0
  43. package/dist/browser/modules/archive/utils/async-queue.js +103 -0
  44. package/dist/browser/modules/archive/utils/bytes.js +16 -16
  45. package/dist/browser/modules/archive/utils/compressibility.d.ts +10 -0
  46. package/dist/browser/modules/archive/utils/compressibility.js +57 -0
  47. package/dist/browser/modules/archive/utils/parse-buffer.js +21 -23
  48. package/dist/browser/modules/archive/utils/pattern-scanner.d.ts +21 -0
  49. package/dist/browser/modules/archive/utils/pattern-scanner.js +27 -0
  50. package/dist/browser/modules/archive/utils/timestamps.js +62 -1
  51. package/dist/browser/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  52. package/dist/browser/modules/archive/utils/zip-extra-fields.js +26 -14
  53. package/dist/browser/modules/archive/zip/index.d.ts +42 -0
  54. package/dist/browser/modules/archive/zip/index.js +157 -0
  55. package/dist/browser/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +28 -5
  56. package/dist/browser/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
  57. package/dist/browser/modules/archive/zip/zip-bytes.d.ts +73 -0
  58. package/dist/browser/modules/archive/zip/zip-bytes.js +239 -0
  59. package/dist/{esm/modules/archive → browser/modules/archive/zip}/zip-entry-metadata.js +3 -3
  60. package/dist/browser/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
  61. package/dist/browser/modules/archive/zip-spec/zip-records.js +126 -0
  62. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +1 -1
  63. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  64. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +1 -1
  65. package/dist/browser/modules/excel/utils/ooxml-validator.d.ts +48 -0
  66. package/dist/browser/modules/excel/utils/ooxml-validator.js +469 -0
  67. package/dist/browser/modules/excel/utils/parse-sax.d.ts +3 -0
  68. package/dist/browser/modules/excel/utils/parse-sax.js +32 -13
  69. package/dist/browser/modules/excel/worksheet.js +5 -2
  70. package/dist/browser/modules/excel/xlsx/xform/core/app-xform.js +3 -3
  71. package/dist/browser/modules/excel/xlsx/xform/core/core-xform.js +56 -68
  72. package/dist/browser/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -0
  73. package/dist/browser/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
  74. package/dist/browser/modules/excel/xlsx/xform/drawing/sp-xform.d.ts +18 -0
  75. package/dist/browser/modules/excel/xlsx/xform/drawing/sp-xform.js +112 -0
  76. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +6 -1
  77. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
  78. package/dist/browser/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
  79. package/dist/browser/modules/excel/xlsx/xform/list-xform.js +8 -10
  80. package/dist/browser/modules/excel/xlsx/xform/sheet/page-setup-xform.d.ts +1 -0
  81. package/dist/browser/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
  82. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +110 -12
  83. package/dist/browser/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
  84. package/dist/browser/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
  85. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +11 -10
  86. package/dist/browser/modules/excel/xlsx/xlsx.js +1 -1
  87. package/dist/browser/modules/stream/base-transform.d.ts +3 -0
  88. package/dist/browser/modules/stream/base-transform.js +34 -20
  89. package/dist/browser/modules/stream/buffered-stream.d.ts +2 -12
  90. package/dist/browser/modules/stream/chunked-builder.js +4 -4
  91. package/dist/browser/modules/stream/index.browser.d.ts +13 -19
  92. package/dist/browser/modules/stream/index.browser.js +10 -22
  93. package/dist/browser/modules/stream/index.d.ts +18 -41
  94. package/dist/browser/modules/stream/index.js +15 -44
  95. package/dist/browser/modules/stream/internal/event-utils.d.ts +17 -0
  96. package/dist/browser/modules/stream/internal/event-utils.js +40 -0
  97. package/dist/browser/modules/stream/internal/type-guards.d.ts +9 -0
  98. package/dist/browser/modules/stream/internal/type-guards.js +24 -0
  99. package/dist/browser/modules/stream/pull-stream.d.ts +5 -6
  100. package/dist/browser/modules/stream/pull-stream.js +107 -43
  101. package/dist/browser/modules/stream/shared.d.ts +1 -1
  102. package/dist/browser/modules/stream/shared.js +7 -4
  103. package/dist/browser/modules/stream/streams.browser.d.ts +32 -44
  104. package/dist/browser/modules/stream/streams.browser.js +921 -836
  105. package/dist/browser/modules/stream/streams.d.ts +4 -20
  106. package/dist/browser/modules/stream/streams.js +146 -95
  107. package/dist/browser/modules/stream/utils.js +5 -38
  108. package/dist/cjs/modules/archive/{compress.base.js → compression/compress.base.js} +1 -1
  109. package/dist/cjs/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
  110. package/dist/cjs/modules/archive/{compress.js → compression/compress.js} +1 -1
  111. package/dist/cjs/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  112. package/dist/cjs/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  113. package/dist/cjs/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  114. package/dist/cjs/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  115. package/dist/cjs/modules/archive/defaults.js +7 -4
  116. package/dist/cjs/modules/archive/index.base.js +9 -19
  117. package/dist/cjs/modules/archive/index.browser.js +4 -10
  118. package/dist/cjs/modules/archive/index.js +4 -8
  119. package/dist/cjs/modules/archive/internal/byte-queue.js +411 -0
  120. package/dist/cjs/modules/archive/io/archive-sink.js +49 -0
  121. package/dist/cjs/modules/archive/io/archive-source.js +105 -0
  122. package/dist/cjs/modules/archive/unzip/index.js +170 -0
  123. package/dist/cjs/modules/archive/unzip/stream.base.js +1044 -0
  124. package/dist/cjs/modules/archive/{parse.browser.js → unzip/stream.browser.js} +372 -111
  125. package/dist/cjs/modules/archive/{parse.js → unzip/stream.js} +9 -8
  126. package/dist/cjs/modules/archive/{zip-parser.js → unzip/zip-parser.js} +47 -33
  127. package/dist/cjs/modules/archive/utils/async-queue.js +106 -0
  128. package/dist/cjs/modules/archive/utils/bytes.js +16 -16
  129. package/dist/cjs/modules/archive/utils/compressibility.js +60 -0
  130. package/dist/cjs/modules/archive/utils/parse-buffer.js +21 -23
  131. package/dist/cjs/modules/archive/utils/pattern-scanner.js +31 -0
  132. package/dist/cjs/modules/archive/utils/timestamps.js +64 -3
  133. package/dist/cjs/modules/archive/utils/zip-extra-fields.js +26 -14
  134. package/dist/cjs/modules/archive/zip/index.js +162 -0
  135. package/dist/cjs/modules/archive/{streaming-zip.js → zip/stream.js} +194 -50
  136. package/dist/cjs/modules/archive/zip/zip-bytes.js +242 -0
  137. package/dist/cjs/modules/archive/{zip-entry-metadata.js → zip/zip-entry-metadata.js} +5 -5
  138. package/dist/cjs/modules/archive/zip-spec/zip-records.js +136 -0
  139. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +2 -2
  140. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +4 -4
  141. package/dist/cjs/modules/excel/utils/ooxml-validator.js +475 -0
  142. package/dist/cjs/modules/excel/utils/parse-sax.js +32 -13
  143. package/dist/cjs/modules/excel/worksheet.js +5 -2
  144. package/dist/cjs/modules/excel/xlsx/xform/core/app-xform.js +3 -3
  145. package/dist/cjs/modules/excel/xlsx/xform/core/core-xform.js +56 -68
  146. package/dist/cjs/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
  147. package/dist/cjs/modules/excel/xlsx/xform/drawing/sp-xform.js +115 -0
  148. package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
  149. package/dist/cjs/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
  150. package/dist/cjs/modules/excel/xlsx/xform/list-xform.js +8 -10
  151. package/dist/cjs/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
  152. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +110 -12
  153. package/dist/cjs/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
  154. package/dist/cjs/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
  155. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +14 -13
  156. package/dist/cjs/modules/excel/xlsx/xlsx.js +2 -2
  157. package/dist/cjs/modules/stream/base-transform.js +34 -20
  158. package/dist/cjs/modules/stream/chunked-builder.js +4 -4
  159. package/dist/cjs/modules/stream/index.browser.js +10 -17
  160. package/dist/cjs/modules/stream/index.js +15 -39
  161. package/dist/cjs/modules/stream/internal/event-utils.js +43 -0
  162. package/dist/cjs/modules/stream/internal/type-guards.js +30 -0
  163. package/dist/cjs/modules/stream/pull-stream.js +107 -43
  164. package/dist/cjs/modules/stream/shared.js +7 -4
  165. package/dist/cjs/modules/stream/streams.browser.js +927 -847
  166. package/dist/cjs/modules/stream/streams.js +156 -107
  167. package/dist/cjs/modules/stream/utils.js +3 -36
  168. package/dist/esm/index.browser.js +12 -0
  169. package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.base.js +1 -1
  170. package/dist/esm/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
  171. package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.js +1 -1
  172. package/dist/esm/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  173. package/dist/esm/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  174. package/dist/esm/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  175. package/dist/esm/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  176. package/dist/esm/modules/archive/defaults.js +6 -3
  177. package/dist/esm/modules/archive/index.base.js +3 -6
  178. package/dist/esm/modules/archive/index.browser.js +3 -7
  179. package/dist/esm/modules/archive/index.js +3 -5
  180. package/dist/esm/modules/archive/internal/byte-queue.js +407 -0
  181. package/dist/esm/modules/archive/io/archive-sink.js +45 -0
  182. package/dist/esm/modules/archive/io/archive-source.js +100 -0
  183. package/dist/esm/modules/archive/unzip/index.js +164 -0
  184. package/dist/esm/modules/archive/unzip/stream.base.js +1022 -0
  185. package/dist/esm/modules/archive/{parse.browser.js → unzip/stream.browser.js} +371 -110
  186. package/dist/{browser/modules/archive/parse.js → esm/modules/archive/unzip/stream.js} +6 -5
  187. package/dist/{browser/modules/archive → esm/modules/archive/unzip}/zip-parser.js +38 -24
  188. package/dist/esm/modules/archive/utils/async-queue.js +103 -0
  189. package/dist/esm/modules/archive/utils/bytes.js +16 -16
  190. package/dist/esm/modules/archive/utils/compressibility.js +57 -0
  191. package/dist/esm/modules/archive/utils/parse-buffer.js +21 -23
  192. package/dist/esm/modules/archive/utils/pattern-scanner.js +27 -0
  193. package/dist/esm/modules/archive/utils/timestamps.js +62 -1
  194. package/dist/esm/modules/archive/utils/zip-extra-fields.js +26 -14
  195. package/dist/esm/modules/archive/zip/index.js +157 -0
  196. package/dist/esm/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
  197. package/dist/esm/modules/archive/zip/zip-bytes.js +239 -0
  198. package/dist/{browser/modules/archive → esm/modules/archive/zip}/zip-entry-metadata.js +3 -3
  199. package/dist/esm/modules/archive/zip-spec/zip-records.js +126 -0
  200. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +1 -1
  201. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +1 -1
  202. package/dist/esm/modules/excel/utils/ooxml-validator.js +469 -0
  203. package/dist/esm/modules/excel/utils/parse-sax.js +32 -13
  204. package/dist/esm/modules/excel/worksheet.js +5 -2
  205. package/dist/esm/modules/excel/xlsx/xform/core/app-xform.js +3 -3
  206. package/dist/esm/modules/excel/xlsx/xform/core/core-xform.js +56 -68
  207. package/dist/esm/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
  208. package/dist/esm/modules/excel/xlsx/xform/drawing/sp-xform.js +112 -0
  209. package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
  210. package/dist/esm/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
  211. package/dist/esm/modules/excel/xlsx/xform/list-xform.js +8 -10
  212. package/dist/esm/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
  213. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +110 -12
  214. package/dist/esm/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
  215. package/dist/esm/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
  216. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +11 -10
  217. package/dist/esm/modules/excel/xlsx/xlsx.js +1 -1
  218. package/dist/esm/modules/stream/base-transform.js +34 -20
  219. package/dist/esm/modules/stream/chunked-builder.js +4 -4
  220. package/dist/esm/modules/stream/index.browser.js +10 -22
  221. package/dist/esm/modules/stream/index.js +15 -44
  222. package/dist/esm/modules/stream/internal/event-utils.js +40 -0
  223. package/dist/esm/modules/stream/internal/type-guards.js +24 -0
  224. package/dist/esm/modules/stream/pull-stream.js +107 -43
  225. package/dist/esm/modules/stream/shared.js +7 -4
  226. package/dist/esm/modules/stream/streams.browser.js +921 -836
  227. package/dist/esm/modules/stream/streams.js +146 -95
  228. package/dist/esm/modules/stream/utils.js +5 -38
  229. package/dist/iife/THIRD_PARTY_NOTICES.md +0 -31
  230. package/dist/iife/excelts.iife.js +6592 -4537
  231. package/dist/iife/excelts.iife.js.map +1 -1
  232. package/dist/iife/excelts.iife.min.js +103 -31
  233. package/dist/types/index.browser.d.ts +1 -0
  234. package/dist/{browser/modules/archive → types/modules/archive/compression}/compress.browser.d.ts +2 -8
  235. package/dist/types/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +1 -1
  236. package/dist/types/modules/archive/defaults.d.ts +1 -0
  237. package/dist/types/modules/archive/index.base.d.ts +4 -4
  238. package/dist/types/modules/archive/index.browser.d.ts +3 -4
  239. package/dist/types/modules/archive/index.d.ts +3 -4
  240. package/dist/types/modules/archive/internal/byte-queue.d.ts +33 -0
  241. package/dist/types/modules/archive/io/archive-sink.d.ts +8 -0
  242. package/dist/types/modules/archive/io/archive-source.d.ts +6 -0
  243. package/dist/types/modules/archive/unzip/index.d.ts +40 -0
  244. package/dist/types/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +38 -4
  245. package/dist/types/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +2 -2
  246. package/dist/types/modules/archive/{parse.d.ts → unzip/stream.d.ts} +3 -3
  247. package/dist/types/modules/archive/{zip-parser.d.ts → unzip/zip-parser.d.ts} +1 -1
  248. package/dist/types/modules/archive/utils/async-queue.d.ts +7 -0
  249. package/dist/types/modules/archive/utils/compressibility.d.ts +10 -0
  250. package/dist/types/modules/archive/utils/pattern-scanner.d.ts +21 -0
  251. package/dist/types/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  252. package/dist/types/modules/archive/zip/index.d.ts +42 -0
  253. package/dist/types/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +29 -6
  254. package/dist/types/modules/archive/zip/zip-bytes.d.ts +73 -0
  255. package/dist/types/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +1 -1
  256. package/dist/types/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
  257. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  258. package/dist/types/modules/excel/utils/ooxml-validator.d.ts +48 -0
  259. package/dist/types/modules/excel/utils/parse-sax.d.ts +3 -0
  260. package/dist/types/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -0
  261. package/dist/types/modules/excel/xlsx/xform/drawing/sp-xform.d.ts +18 -0
  262. package/dist/types/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +6 -1
  263. package/dist/types/modules/excel/xlsx/xform/sheet/page-setup-xform.d.ts +1 -0
  264. package/dist/types/modules/stream/base-transform.d.ts +3 -0
  265. package/dist/types/modules/stream/buffered-stream.d.ts +2 -12
  266. package/dist/types/modules/stream/index.browser.d.ts +13 -19
  267. package/dist/types/modules/stream/index.d.ts +18 -41
  268. package/dist/types/modules/stream/internal/event-utils.d.ts +17 -0
  269. package/dist/types/modules/stream/internal/type-guards.d.ts +9 -0
  270. package/dist/types/modules/stream/pull-stream.d.ts +5 -6
  271. package/dist/types/modules/stream/shared.d.ts +1 -1
  272. package/dist/types/modules/stream/streams.browser.d.ts +32 -44
  273. package/dist/types/modules/stream/streams.d.ts +4 -20
  274. package/package.json +14 -10
  275. package/dist/browser/modules/archive/byte-queue.d.ts +0 -18
  276. package/dist/browser/modules/archive/byte-queue.js +0 -125
  277. package/dist/browser/modules/archive/parse.base.js +0 -644
  278. package/dist/browser/modules/archive/utils/zip-extra.d.ts +0 -18
  279. package/dist/browser/modules/archive/utils/zip-extra.js +0 -68
  280. package/dist/browser/modules/archive/zip-builder.d.ts +0 -117
  281. package/dist/browser/modules/archive/zip-builder.js +0 -292
  282. package/dist/browser/modules/archive/zip-constants.d.ts +0 -18
  283. package/dist/browser/modules/archive/zip-constants.js +0 -23
  284. package/dist/browser/modules/archive/zip-records.js +0 -84
  285. package/dist/cjs/modules/archive/byte-queue.js +0 -129
  286. package/dist/cjs/modules/archive/parse.base.js +0 -666
  287. package/dist/cjs/modules/archive/utils/zip-extra.js +0 -74
  288. package/dist/cjs/modules/archive/zip-builder.js +0 -297
  289. package/dist/cjs/modules/archive/zip-constants.js +0 -26
  290. package/dist/cjs/modules/archive/zip-records.js +0 -90
  291. package/dist/esm/modules/archive/byte-queue.js +0 -125
  292. package/dist/esm/modules/archive/parse.base.js +0 -644
  293. package/dist/esm/modules/archive/utils/zip-extra.js +0 -68
  294. package/dist/esm/modules/archive/zip-builder.js +0 -292
  295. package/dist/esm/modules/archive/zip-constants.js +0 -23
  296. package/dist/esm/modules/archive/zip-records.js +0 -84
  297. package/dist/types/modules/archive/byte-queue.d.ts +0 -18
  298. package/dist/types/modules/archive/utils/zip-extra.d.ts +0 -18
  299. package/dist/types/modules/archive/zip-builder.d.ts +0 -117
  300. package/dist/types/modules/archive/zip-constants.d.ts +0 -18
  301. /package/dist/browser/modules/archive/{compress.base.d.ts → compression/compress.base.d.ts} +0 -0
  302. /package/dist/browser/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
  303. /package/dist/browser/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  304. /package/dist/browser/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  305. /package/dist/browser/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
  306. /package/dist/browser/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
  307. /package/dist/browser/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  308. /package/dist/browser/modules/archive/{extract.js → unzip/extract.js} +0 -0
  309. /package/dist/browser/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +0 -0
  310. /package/dist/browser/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
  311. /package/dist/browser/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  312. /package/dist/cjs/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  313. /package/dist/cjs/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  314. /package/dist/cjs/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  315. /package/dist/cjs/modules/archive/{extract.js → unzip/extract.js} +0 -0
  316. /package/dist/cjs/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  317. /package/dist/esm/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  318. /package/dist/esm/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  319. /package/dist/esm/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  320. /package/dist/esm/modules/archive/{extract.js → unzip/extract.js} +0 -0
  321. /package/dist/esm/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  322. /package/dist/types/modules/archive/{compress.base.d.ts → compression/compress.base.d.ts} +0 -0
  323. /package/dist/types/modules/archive/{compress.d.ts → compression/compress.d.ts} +0 -0
  324. /package/dist/types/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
  325. /package/dist/types/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +0 -0
  326. /package/dist/types/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +0 -0
  327. /package/dist/types/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
  328. /package/dist/types/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
  329. /package/dist/types/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +0 -0
  330. /package/dist/types/modules/archive/{extract.d.ts → unzip/extract.d.ts} +0 -0
  331. /package/dist/types/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
@@ -12,7 +12,7 @@
12
12
  * - Edge >= 89
13
13
  */
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.promises = exports.consumers = exports.streamToBuffer = exports.BufferedStream = exports.BufferChunk = exports.StringChunk = exports.PullStream = exports.Collector = exports.PassThrough = exports.Duplex = exports.Transform = exports.Writable = exports.Readable = void 0;
15
+ exports.promises = exports.consumers = exports.streamToBuffer = exports.BufferChunk = exports.StringChunk = exports.BufferedStream = exports.PullStream = exports.Collector = exports.PassThrough = exports.Duplex = exports.Transform = exports.Writable = exports.Readable = void 0;
16
16
  exports.normalizeWritable = normalizeWritable;
17
17
  exports.createReadable = createReadable;
18
18
  exports.createReadableFromAsyncIterable = createReadableFromAsyncIterable;
@@ -53,8 +53,47 @@ exports.isWritable = isWritable;
53
53
  exports.duplexPair = duplexPair;
54
54
  const event_emitter_1 = require("./event-emitter.js");
55
55
  const pull_stream_1 = require("./pull-stream.js");
56
+ Object.defineProperty(exports, "PullStream", { enumerable: true, get: function () { return pull_stream_1.PullStream; } });
56
57
  const buffered_stream_1 = require("./buffered-stream.js");
58
+ Object.defineProperty(exports, "BufferedStream", { enumerable: true, get: function () { return buffered_stream_1.BufferedStream; } });
59
+ Object.defineProperty(exports, "BufferChunk", { enumerable: true, get: function () { return buffered_stream_1.BufferChunk; } });
60
+ Object.defineProperty(exports, "StringChunk", { enumerable: true, get: function () { return buffered_stream_1.StringChunk; } });
57
61
  const shared_1 = require("./shared.js");
62
+ const type_guards_1 = require("./internal/type-guards.js");
63
+ const removeEmitterListener = (emitter, event, listener) => {
64
+ if (typeof emitter.off === "function") {
65
+ emitter.off(event, listener);
66
+ }
67
+ else if (typeof emitter.removeListener === "function") {
68
+ emitter.removeListener(event, listener);
69
+ }
70
+ };
71
+ const addEmitterListener = (emitter, event, listener, options) => {
72
+ if (options?.once && typeof emitter.once === "function") {
73
+ emitter.once(event, listener);
74
+ }
75
+ else {
76
+ emitter.on(event, listener);
77
+ }
78
+ return () => removeEmitterListener(emitter, event, listener);
79
+ };
80
+ const createListenerRegistry = () => {
81
+ const listeners = [];
82
+ return {
83
+ add: (emitter, event, listener) => {
84
+ listeners.push(addEmitterListener(emitter, event, listener));
85
+ },
86
+ once: (emitter, event, listener) => {
87
+ listeners.push(addEmitterListener(emitter, event, listener, { once: true }));
88
+ },
89
+ cleanup: () => {
90
+ for (let i = listeners.length - 1; i >= 0; i--) {
91
+ listeners[i]();
92
+ }
93
+ listeners.length = 0;
94
+ }
95
+ };
96
+ };
58
97
  // =============================================================================
59
98
  // Readable Stream Wrapper
60
99
  // =============================================================================
@@ -71,6 +110,7 @@ class Readable extends event_emitter_1.EventEmitter {
71
110
  this._bufferSize = 0;
72
111
  this._reading = false;
73
112
  this._ended = false;
113
+ this._endEmitted = false;
74
114
  this._destroyed = false;
75
115
  this._errored = null;
76
116
  this._closed = false;
@@ -127,20 +167,7 @@ class Readable extends event_emitter_1.EventEmitter {
127
167
  */
128
168
  static from(iterable, options) {
129
169
  const readable = new Readable({ ...options, objectMode: options?.objectMode ?? true });
130
- (async () => {
131
- try {
132
- for await (const chunk of iterable) {
133
- if (!readable.push(chunk)) {
134
- // Backpressure
135
- await new Promise(resolve => setTimeout(resolve, 0));
136
- }
137
- }
138
- readable.push(null);
139
- }
140
- catch (err) {
141
- readable.destroy(err);
142
- }
143
- })();
170
+ pumpAsyncIterableToReadable(readable, toAsyncIterable(iterable));
144
171
  return readable;
145
172
  }
146
173
  /**
@@ -185,16 +212,30 @@ class Readable extends event_emitter_1.EventEmitter {
185
212
  // Controller may already be closed
186
213
  }
187
214
  }
188
- this.emit("end");
215
+ // Emit 'end' only after buffered data is fully drained.
216
+ // This avoids premature 'end' when producers push null while paused.
217
+ if (this._bufferedLength() === 0) {
218
+ this._emitEndOnce();
219
+ }
189
220
  // Note: Don't call destroy() here, let the stream be consumed naturally
190
221
  // The reader will return done:true when it finishes reading
191
222
  return false;
192
223
  }
224
+ // Keep the internal Web ReadableStream in sync for controllable streams.
225
+ // For external Web streams (_webStreamMode=true), push() is not the data source.
226
+ if (controller && !this._webStreamMode) {
227
+ try {
228
+ controller.enqueue(chunk);
229
+ }
230
+ catch {
231
+ // Controller may be closed/errored; Node-side buffering/events still work.
232
+ }
233
+ }
193
234
  if (this._flowing) {
194
235
  // In flowing mode, emit data directly without buffering or enqueueing
195
236
  // const chunkStr = chunk instanceof Uint8Array ? new TextDecoder().decode(chunk.slice(0, 50)) : String(chunk).slice(0, 50);
196
237
  // console.log(`[Readable#${this._id}.push FLOWING] emit data size:${(chunk as any).length || (chunk as any).byteLength} start:"${chunkStr}"`);
197
- this.emit("data", chunk);
238
+ this.emit("data", this._applyEncoding(chunk));
198
239
  // Check if stream was paused during emit (backpressure from consumer)
199
240
  if (!this._flowing) {
200
241
  return false;
@@ -219,10 +260,8 @@ class Readable extends event_emitter_1.EventEmitter {
219
260
  if (!this.objectMode) {
220
261
  this._bufferSize += this._getChunkSize(chunk);
221
262
  }
222
- // NOTE: Do NOT enqueue to Web Stream controller here!
223
- // In push mode, _buffer is the only source of data for data events.
224
- // Web Stream is only used for async iteration when not in push mode.
225
- // Enqueueing here would cause data duplication when _startReading is also running.
263
+ // NOTE: We still buffer for Node-style read()/data semantics.
264
+ // The internal Web ReadableStream is also fed via controller.enqueue() above.
226
265
  // Emit readable event when buffer goes from empty to having data
227
266
  if (wasEmpty) {
228
267
  queueMicrotask(() => this.emit("readable"));
@@ -236,6 +275,13 @@ class Readable extends event_emitter_1.EventEmitter {
236
275
  return this._bufferSize < this.readableHighWaterMark;
237
276
  }
238
277
  }
278
+ _emitEndOnce() {
279
+ if (this._endEmitted) {
280
+ return;
281
+ }
282
+ this._endEmitted = true;
283
+ this.emit("end");
284
+ }
239
285
  /**
240
286
  * Put a chunk back at the front of the buffer
241
287
  * Note: unshift is allowed even after end, as it's used to put back already read data
@@ -260,14 +306,22 @@ class Readable extends event_emitter_1.EventEmitter {
260
306
  if (!this.objectMode) {
261
307
  this._bufferSize -= this._getChunkSize(chunk);
262
308
  }
263
- return this._applyEncoding(chunk);
309
+ const decoded = this._applyEncoding(chunk);
310
+ if (this._ended && this._bufferedLength() === 0) {
311
+ queueMicrotask(() => this._emitEndOnce());
312
+ }
313
+ return decoded;
264
314
  }
265
315
  // For binary mode, handle size
266
316
  const chunk = this._bufferShift();
267
317
  if (!this.objectMode) {
268
318
  this._bufferSize -= this._getChunkSize(chunk);
269
319
  }
270
- return this._applyEncoding(chunk);
320
+ const decoded = this._applyEncoding(chunk);
321
+ if (this._ended && this._bufferedLength() === 0) {
322
+ queueMicrotask(() => this._emitEndOnce());
323
+ }
324
+ return decoded;
271
325
  }
272
326
  return null;
273
327
  }
@@ -373,11 +427,11 @@ class Readable extends event_emitter_1.EventEmitter {
373
427
  if (!this.objectMode) {
374
428
  this._bufferSize -= this._getChunkSize(chunk);
375
429
  }
376
- this.emit("data", chunk);
430
+ this.emit("data", this._applyEncoding(chunk));
377
431
  }
378
432
  // If already ended, emit end event
379
433
  if (this._ended && this._bufferedLength() === 0) {
380
- this.emit("end");
434
+ this._emitEndOnce();
381
435
  }
382
436
  else if (this._read) {
383
437
  // Call user-provided read function asynchronously
@@ -440,26 +494,36 @@ class Readable extends event_emitter_1.EventEmitter {
440
494
  }
441
495
  this._pipeTo.push(dest);
442
496
  // Create listeners that we can later remove
497
+ let drainListener;
498
+ const removeDrainListener = () => {
499
+ if (!drainListener) {
500
+ return;
501
+ }
502
+ if (typeof eventTarget.off === "function") {
503
+ eventTarget.off("drain", drainListener);
504
+ }
505
+ else if (typeof eventTarget.removeListener === "function") {
506
+ eventTarget.removeListener("drain", drainListener);
507
+ }
508
+ drainListener = undefined;
509
+ };
443
510
  const dataListener = (chunk) => {
444
511
  // Call destination's write() method (not internal _writable.write())
445
512
  // This ensures Transform.write() logic runs properly
446
513
  const canWrite = dest.write(chunk);
447
514
  if (!canWrite) {
448
515
  this.pause();
449
- if (typeof eventTarget.once === "function") {
450
- eventTarget.once("drain", () => this.resume());
451
- }
452
- else {
453
- const resumeOnce = () => {
454
- if (typeof eventTarget.off === "function") {
455
- eventTarget.off("drain", resumeOnce);
456
- }
457
- else if (typeof eventTarget.removeListener === "function") {
458
- eventTarget.removeListener("drain", resumeOnce);
459
- }
516
+ // Install a removable, once-style drain listener.
517
+ if (!drainListener) {
518
+ drainListener = () => {
519
+ removeDrainListener();
460
520
  this.resume();
461
521
  };
462
- eventTarget.on("drain", resumeOnce);
522
+ eventTarget.on("drain", drainListener);
523
+ const entry = this._pipeListeners.get(dest);
524
+ if (entry) {
525
+ entry.drain = drainListener;
526
+ }
463
527
  }
464
528
  }
465
529
  };
@@ -479,7 +543,8 @@ class Readable extends event_emitter_1.EventEmitter {
479
543
  this._pipeListeners.set(dest, {
480
544
  data: dataListener,
481
545
  end: endListener,
482
- error: errorListener
546
+ error: errorListener,
547
+ eventTarget
483
548
  });
484
549
  this.on("data", dataListener);
485
550
  this.once("end", endListener);
@@ -502,6 +567,14 @@ class Readable extends event_emitter_1.EventEmitter {
502
567
  this.off("data", listeners.data);
503
568
  this.off("end", listeners.end);
504
569
  this.off("error", listeners.error);
570
+ if (listeners.drain) {
571
+ if (typeof listeners.eventTarget?.off === "function") {
572
+ listeners.eventTarget.off("drain", listeners.drain);
573
+ }
574
+ else if (typeof listeners.eventTarget?.removeListener === "function") {
575
+ listeners.eventTarget.removeListener("drain", listeners.drain);
576
+ }
577
+ }
505
578
  this._pipeListeners.delete(destination);
506
579
  }
507
580
  }
@@ -513,6 +586,14 @@ class Readable extends event_emitter_1.EventEmitter {
513
586
  this.off("data", listeners.data);
514
587
  this.off("end", listeners.end);
515
588
  this.off("error", listeners.error);
589
+ if (listeners.drain) {
590
+ if (typeof listeners.eventTarget?.off === "function") {
591
+ listeners.eventTarget.off("drain", listeners.drain);
592
+ }
593
+ else if (typeof listeners.eventTarget?.removeListener === "function") {
594
+ listeners.eventTarget.removeListener("drain", listeners.drain);
595
+ }
596
+ }
516
597
  this._pipeListeners.delete(target);
517
598
  }
518
599
  }
@@ -531,12 +612,26 @@ class Readable extends event_emitter_1.EventEmitter {
531
612
  }
532
613
  this._destroyed = true;
533
614
  this._ended = true;
615
+ // Ensure we detach from destinations to avoid leaking listeners.
616
+ this.unpipe();
534
617
  if (error) {
535
618
  this._errored = error;
536
619
  this.emit("error", error);
537
620
  }
538
621
  if (this._reader) {
539
- this._reader.cancel().catch(() => { });
622
+ const reader = this._reader;
623
+ this._reader = null;
624
+ reader
625
+ .cancel()
626
+ .catch(() => { })
627
+ .finally(() => {
628
+ try {
629
+ reader.releaseLock();
630
+ }
631
+ catch {
632
+ // Ignore if a read is still pending
633
+ }
634
+ });
540
635
  }
541
636
  this._closed = true;
542
637
  this.emit("close");
@@ -615,18 +710,38 @@ class Readable extends event_emitter_1.EventEmitter {
615
710
  const { done, value } = await this._reader.read();
616
711
  // Check _pushMode again after async read - if push() was called, stop reading
617
712
  if (this._pushMode) {
713
+ if (this._reader) {
714
+ const reader = this._reader;
715
+ this._reader = null;
716
+ try {
717
+ reader.releaseLock();
718
+ }
719
+ catch {
720
+ // Ignore if a read is still pending
721
+ }
722
+ }
618
723
  break;
619
724
  }
620
725
  if (done) {
621
726
  this._ended = true;
622
- this.emit("end");
727
+ this._emitEndOnce();
728
+ if (this._reader) {
729
+ const reader = this._reader;
730
+ this._reader = null;
731
+ try {
732
+ reader.releaseLock();
733
+ }
734
+ catch {
735
+ // Ignore if a read is still pending
736
+ }
737
+ }
623
738
  break;
624
739
  }
625
740
  if (value !== undefined) {
626
741
  // In flowing mode, emit data directly without buffering
627
742
  // Only buffer if not flowing (paused mode)
628
743
  if (this._flowing) {
629
- this.emit("data", value);
744
+ this.emit("data", this._applyEncoding(value));
630
745
  }
631
746
  else {
632
747
  this._buffer.push(value);
@@ -639,6 +754,16 @@ class Readable extends event_emitter_1.EventEmitter {
639
754
  }
640
755
  catch (err) {
641
756
  this.emit("error", err);
757
+ if (this._reader) {
758
+ const reader = this._reader;
759
+ this._reader = null;
760
+ try {
761
+ reader.releaseLock();
762
+ }
763
+ catch {
764
+ // Ignore if a read is still pending
765
+ }
766
+ }
642
767
  }
643
768
  finally {
644
769
  this._reading = false;
@@ -646,7 +771,8 @@ class Readable extends event_emitter_1.EventEmitter {
646
771
  }
647
772
  /**
648
773
  * Async iterator support
649
- * Uses Web Stream reader for non-push mode, event-based for push mode
774
+ * Uses a unified event-queue iterator with simple backpressure.
775
+ * This matches Node's behavior more closely (iterator drives flowing mode).
650
776
  */
651
777
  async *[Symbol.asyncIterator]() {
652
778
  // First yield any buffered data
@@ -655,117 +781,124 @@ class Readable extends event_emitter_1.EventEmitter {
655
781
  if (!this.objectMode) {
656
782
  this._bufferSize -= this._getChunkSize(chunk);
657
783
  }
658
- yield chunk;
784
+ yield this._applyEncoding(chunk);
659
785
  }
660
- // If already ended, we're done
661
786
  if (this._ended) {
662
787
  return;
663
788
  }
664
- // For controllable streams (not created from external Web Stream),
665
- // use event-based iteration since data comes from push() calls
666
- if (!this._webStreamMode) {
667
- // Create a promise-based queue for incoming data
668
- const dataQueue = [];
669
- let resolveNext = null;
670
- let rejectNext = null;
671
- let done = false;
672
- let streamError = null;
673
- let dataQueueIndex = 0;
674
- const dataHandler = (chunk) => {
675
- if (resolveNext) {
676
- resolveNext(chunk);
677
- resolveNext = null;
678
- rejectNext = null;
679
- }
680
- else {
681
- dataQueue.push(chunk);
682
- }
683
- };
684
- const endHandler = () => {
685
- done = true;
686
- if (resolveNext) {
687
- resolveNext(null);
688
- resolveNext = null;
689
- rejectNext = null;
690
- }
691
- };
692
- const errorHandler = (err) => {
693
- done = true;
694
- streamError = err;
695
- if (rejectNext) {
696
- rejectNext(err);
697
- resolveNext = null;
698
- rejectNext = null;
699
- }
700
- };
701
- const closeHandler = () => {
702
- // If stream closed without end event (e.g., after destroy()),
703
- // treat it as done
704
- done = true;
705
- if (resolveNext) {
706
- resolveNext(null);
707
- resolveNext = null;
708
- rejectNext = null;
709
- }
710
- };
711
- this.on("data", dataHandler);
712
- this.on("end", endHandler);
713
- this.on("error", errorHandler);
714
- this.on("close", closeHandler);
715
- try {
716
- // Enter flowing mode
717
- this.resume();
718
- while (!done || dataQueueIndex < dataQueue.length) {
719
- // Check for error before processing
720
- if (streamError) {
721
- throw streamError;
722
- }
723
- if (dataQueueIndex < dataQueue.length) {
724
- const chunk = dataQueue[dataQueueIndex++];
725
- if (dataQueueIndex >= 1024 && dataQueueIndex * 2 >= dataQueue.length) {
726
- dataQueue.splice(0, dataQueueIndex);
727
- dataQueueIndex = 0;
728
- }
729
- yield chunk;
730
- }
731
- else if (!done) {
732
- const chunk = await new Promise((resolve, reject) => {
733
- resolveNext = resolve;
734
- rejectNext = reject;
735
- });
736
- if (chunk !== null) {
737
- yield chunk;
738
- }
739
- }
740
- }
741
- // Check for error after loop
742
- if (streamError) {
743
- throw streamError;
744
- }
789
+ const highWaterMark = this.readableHighWaterMark;
790
+ const lowWaterMark = Math.max(0, Math.floor(highWaterMark / 2));
791
+ const chunkSizeForBackpressure = (chunk) => {
792
+ if (this.objectMode) {
793
+ return 1;
745
794
  }
746
- finally {
747
- this.off("data", dataHandler);
748
- this.off("end", endHandler);
749
- this.off("error", errorHandler);
750
- this.off("close", closeHandler);
795
+ if (chunk instanceof Uint8Array) {
796
+ return chunk.byteLength;
751
797
  }
752
- return;
753
- }
754
- // For Web Stream mode, use the underlying reader
755
- if (!this._reader) {
756
- this._reader = this._stream.getReader();
757
- }
798
+ if (typeof chunk === "string") {
799
+ return chunk.length;
800
+ }
801
+ return 1;
802
+ };
803
+ const dataQueue = [];
804
+ let dataQueueIndex = 0;
805
+ let queuedSize = 0;
806
+ let resolveNext = null;
807
+ let rejectNext = null;
808
+ let done = false;
809
+ let pausedByIterator = false;
810
+ let streamError = null;
811
+ const dataHandler = (chunk) => {
812
+ // data events are already encoding-aware; do not decode again here.
813
+ if (resolveNext) {
814
+ resolveNext(chunk);
815
+ resolveNext = null;
816
+ rejectNext = null;
817
+ }
818
+ else {
819
+ dataQueue.push(chunk);
820
+ }
821
+ queuedSize += chunkSizeForBackpressure(chunk);
822
+ if (!pausedByIterator && queuedSize >= highWaterMark) {
823
+ pausedByIterator = true;
824
+ this.pause();
825
+ }
826
+ };
827
+ const endHandler = () => {
828
+ done = true;
829
+ if (resolveNext) {
830
+ resolveNext(null);
831
+ resolveNext = null;
832
+ rejectNext = null;
833
+ }
834
+ };
835
+ const closeHandler = () => {
836
+ done = true;
837
+ if (resolveNext) {
838
+ resolveNext(null);
839
+ resolveNext = null;
840
+ rejectNext = null;
841
+ }
842
+ };
843
+ const errorHandler = (err) => {
844
+ done = true;
845
+ streamError = err;
846
+ if (rejectNext) {
847
+ rejectNext(err);
848
+ resolveNext = null;
849
+ rejectNext = null;
850
+ }
851
+ };
852
+ this.on("data", dataHandler);
853
+ this.on("end", endHandler);
854
+ this.on("error", errorHandler);
855
+ this.on("close", closeHandler);
758
856
  try {
857
+ // Iterator consumption should drive the stream.
858
+ this.resume();
759
859
  while (true) {
760
- const { done, value } = await this._reader.read();
860
+ if (streamError) {
861
+ throw streamError;
862
+ }
863
+ if (dataQueueIndex < dataQueue.length) {
864
+ const chunk = dataQueue[dataQueueIndex++];
865
+ queuedSize -= chunkSizeForBackpressure(chunk);
866
+ if (dataQueueIndex >= 1024 && dataQueueIndex * 2 >= dataQueue.length) {
867
+ dataQueue.splice(0, dataQueueIndex);
868
+ dataQueueIndex = 0;
869
+ }
870
+ if (pausedByIterator && queuedSize <= lowWaterMark && !done && !this._destroyed) {
871
+ pausedByIterator = false;
872
+ this.resume();
873
+ }
874
+ yield chunk;
875
+ continue;
876
+ }
761
877
  if (done) {
762
878
  break;
763
879
  }
764
- yield value;
880
+ const chunk = await new Promise((resolve, reject) => {
881
+ resolveNext = resolve;
882
+ rejectNext = reject;
883
+ });
884
+ if (chunk !== null) {
885
+ queuedSize -= chunkSizeForBackpressure(chunk);
886
+ if (pausedByIterator && queuedSize <= lowWaterMark && !done && !this._destroyed) {
887
+ pausedByIterator = false;
888
+ this.resume();
889
+ }
890
+ yield chunk;
891
+ }
892
+ }
893
+ if (streamError) {
894
+ throw streamError;
765
895
  }
766
896
  }
767
897
  finally {
768
- this._reader.releaseLock();
898
+ this.off("data", dataHandler);
899
+ this.off("end", endHandler);
900
+ this.off("error", errorHandler);
901
+ this.off("close", closeHandler);
769
902
  }
770
903
  }
771
904
  /**
@@ -985,6 +1118,32 @@ class Readable extends event_emitter_1.EventEmitter {
985
1118
  }
986
1119
  }
987
1120
  exports.Readable = Readable;
1121
+ function toAsyncIterable(iterable) {
1122
+ if (iterable && typeof iterable[Symbol.asyncIterator] === "function") {
1123
+ return iterable;
1124
+ }
1125
+ return (async function* () {
1126
+ for (const item of iterable) {
1127
+ yield item;
1128
+ }
1129
+ })();
1130
+ }
1131
+ function pumpAsyncIterableToReadable(readable, iterable) {
1132
+ (async () => {
1133
+ try {
1134
+ for await (const chunk of iterable) {
1135
+ if (!readable.push(chunk)) {
1136
+ // Simple backpressure: yield to consumer.
1137
+ await new Promise(resolve => setTimeout(resolve, 0));
1138
+ }
1139
+ }
1140
+ readable.push(null);
1141
+ }
1142
+ catch (err) {
1143
+ readable.destroy(err);
1144
+ }
1145
+ })();
1146
+ }
988
1147
  // =============================================================================
989
1148
  // Writable Stream Wrapper
990
1149
  // =============================================================================
@@ -1002,10 +1161,12 @@ class Writable extends event_emitter_1.EventEmitter {
1002
1161
  this._closed = false;
1003
1162
  this._pendingWrites = 0;
1004
1163
  this._writableLength = 0;
1164
+ this._needDrain = false;
1005
1165
  this._corked = 0;
1006
1166
  this._corkedChunks = [];
1007
1167
  this._defaultEncoding = "utf8";
1008
1168
  this._aborted = false;
1169
+ this._ownsStream = false;
1009
1170
  this.objectMode = options?.objectMode ?? false;
1010
1171
  this.writableHighWaterMark = options?.highWaterMark ?? 16384;
1011
1172
  this.autoDestroy = options?.autoDestroy ?? true;
@@ -1021,8 +1182,10 @@ class Writable extends event_emitter_1.EventEmitter {
1021
1182
  }
1022
1183
  if (options?.stream) {
1023
1184
  this._stream = options.stream;
1185
+ this._ownsStream = false;
1024
1186
  }
1025
1187
  else {
1188
+ this._ownsStream = true;
1026
1189
  // Create bound references to instance properties/methods for use in WritableStream callbacks
1027
1190
  const getWriteFunc = () => this._writeFunc;
1028
1191
  const getFinalFunc = () => this._finalFunc;
@@ -1129,25 +1292,37 @@ class Writable extends event_emitter_1.EventEmitter {
1129
1292
  this._writableLength += chunkSize;
1130
1293
  return this._writableLength < this.writableHighWaterMark;
1131
1294
  }
1132
- return this._doWrite(chunk, cb);
1295
+ const ok = this._doWrite(chunk, cb);
1296
+ if (!ok) {
1297
+ this._needDrain = true;
1298
+ }
1299
+ return ok;
1133
1300
  }
1134
1301
  _doWrite(chunk, callback) {
1135
1302
  // Track pending writes for writableLength
1136
1303
  const chunkSize = this._getChunkSize(chunk);
1137
1304
  this._pendingWrites++;
1138
1305
  this._writableLength += chunkSize;
1139
- this._getWriter()
1306
+ const writer = this._getWriter();
1307
+ writer
1140
1308
  .write(chunk)
1141
1309
  .then(() => {
1142
1310
  this._pendingWrites--;
1143
1311
  this._writableLength -= chunkSize;
1144
- this.emit("drain");
1312
+ if (this._needDrain && this._writableLength < this.writableHighWaterMark) {
1313
+ this._needDrain = false;
1314
+ this.emit("drain");
1315
+ }
1145
1316
  callback?.(null);
1146
1317
  })
1147
1318
  .catch(err => {
1148
1319
  this._pendingWrites--;
1149
1320
  this._writableLength -= chunkSize;
1150
- this.emit("error", err);
1321
+ // Avoid double-emitting if we're already in an errored/destroyed state.
1322
+ if (!this._destroyed) {
1323
+ this._errored = err;
1324
+ this.emit("error", err);
1325
+ }
1151
1326
  callback?.(err);
1152
1327
  });
1153
1328
  // Return false if we've exceeded high water mark (for backpressure)
@@ -1178,12 +1353,29 @@ class Writable extends event_emitter_1.EventEmitter {
1178
1353
  : callback;
1179
1354
  const finish = async () => {
1180
1355
  try {
1356
+ const writer = this._getWriter();
1181
1357
  if (chunk !== undefined) {
1182
- await this._getWriter().write(chunk);
1358
+ await writer.write(chunk);
1359
+ }
1360
+ await writer.close();
1361
+ if (this._writer === writer) {
1362
+ this._writer = null;
1363
+ try {
1364
+ writer.releaseLock();
1365
+ }
1366
+ catch {
1367
+ // Ignore
1368
+ }
1369
+ }
1370
+ // If we own the underlying Web WritableStream, its `close()` handler already
1371
+ // emits finish/close. For external streams, we must emit finish ourselves.
1372
+ if (!this._ownsStream) {
1373
+ this._finished = true;
1374
+ this.emit("finish");
1375
+ if (this.emitClose) {
1376
+ this.emit("close");
1377
+ }
1183
1378
  }
1184
- await this._getWriter().close();
1185
- this._finished = true;
1186
- this.emit("finish");
1187
1379
  if (cb) {
1188
1380
  cb();
1189
1381
  }
@@ -1204,12 +1396,24 @@ class Writable extends event_emitter_1.EventEmitter {
1204
1396
  }
1205
1397
  this._destroyed = true;
1206
1398
  this._ended = true;
1207
- if (error) {
1399
+ if (error && !this._errored) {
1208
1400
  this._errored = error;
1209
1401
  this.emit("error", error);
1210
1402
  }
1211
1403
  if (this._writer) {
1212
- this._writer.abort(error).catch(() => { });
1404
+ const writer = this._writer;
1405
+ this._writer = null;
1406
+ writer
1407
+ .abort(error)
1408
+ .catch(() => { })
1409
+ .finally(() => {
1410
+ try {
1411
+ writer.releaseLock();
1412
+ }
1413
+ catch {
1414
+ // Ignore
1415
+ }
1416
+ });
1213
1417
  }
1214
1418
  this._closed = true;
1215
1419
  this.emit("close");
@@ -1361,342 +1565,259 @@ function normalizeWritable(stream) {
1361
1565
  */
1362
1566
  class Transform extends event_emitter_1.EventEmitter {
1363
1567
  /**
1364
- * Push data to the readable side (Node.js compatibility)
1365
- * Can be called from within transform callback
1568
+ * Push data to the readable side (Node.js compatibility).
1569
+ * Intended to be called from within transform/flush.
1366
1570
  */
1367
1571
  push(chunk) {
1368
- if (chunk === null) {
1369
- return false;
1370
- }
1371
- if (this._transformController) {
1372
- // If we're in a transform callback, enqueue directly
1373
- this._transformController.enqueue(chunk);
1374
- }
1375
- else {
1376
- // Otherwise buffer for later
1377
- this._pushBuffer.push(chunk);
1378
- }
1379
- return true;
1572
+ return this._readable.push(chunk);
1380
1573
  }
1381
1574
  constructor(options) {
1382
1575
  super();
1383
- this._ended = false;
1384
1576
  this._destroyed = false;
1577
+ this._ended = false;
1385
1578
  this._errored = false;
1386
- // Buffer for Node.js style push() calls during transform
1387
- this._pushBuffer = [];
1388
- // Controller for enqueueing pushed data (set during transform execution)
1389
- this._transformController = null;
1390
- // Buffer for writes that occur after end() but before writable is closed
1391
- this._pendingEndWrites = [];
1392
- // Whether end() has been called but writable not yet closed
1393
- this._endPending = false;
1394
- // Track if we've already set up data forwarding
1395
1579
  this._dataForwardingSetup = false;
1396
- /** @internal - whether we have a data event consumer */
1397
- this._hasDataConsumer = false;
1398
- /** @internal - whether we're auto-consuming the readable */
1399
- this._readableConsuming = false;
1400
- /** @internal - buffer for auto-consumed data */
1401
- this._autoConsumedBuffer = [];
1402
- this._autoConsumedBufferIndex = 0;
1403
- /** @internal - whether auto-consume has ended */
1404
- this._autoConsumeEnded = false;
1405
- /** @internal - promise that resolves when auto-consume finishes */
1406
- this._autoConsumePromise = null;
1407
- /** @internal - list of piped destinations for forwarding auto-consumed data */
1408
- this._pipeDestinations = [];
1580
+ this._endTimer = null;
1581
+ this._webStream = null;
1582
+ this._sideForwardingCleanup = null;
1409
1583
  this.objectMode = options?.objectMode ?? false;
1410
- const userTransform = options?.transform;
1411
- const userFlush = options?.flush;
1412
- // Create bound references for use in TransformStream callbacks
1413
- const setController = (ctrl) => {
1414
- this._transformController = ctrl;
1415
- };
1416
- const emitEvent = (event, ...args) => {
1417
- if (event === "error") {
1418
- // Only emit error once to prevent duplicate events
1419
- if (this._errored) {
1420
- return false;
1421
- }
1422
- this._errored = true;
1423
- // Also destroy the writable to prevent further writes
1424
- this._writable.destroy(args[0]);
1584
+ this._transformImpl = options?.transform;
1585
+ this._flushImpl = options?.flush;
1586
+ this._readable = new Readable({
1587
+ objectMode: this.objectMode
1588
+ });
1589
+ this._writable = new Writable({
1590
+ objectMode: this.objectMode,
1591
+ write: (chunk, _encoding, callback) => {
1592
+ this._runTransform(chunk)
1593
+ .then(() => callback(null))
1594
+ .catch(err => callback(err));
1595
+ },
1596
+ final: callback => {
1597
+ this._runFlush()
1598
+ .then(() => {
1599
+ this._readable.push(null);
1600
+ callback(null);
1601
+ })
1602
+ .catch(err => callback(err));
1425
1603
  }
1426
- return this.emit(event, ...args);
1427
- };
1428
- const getInstance = () => this;
1429
- // Check if subclass overrides _transform (for Node.js compatibility)
1430
- // We need to check this at runtime since the subclass constructor runs after super()
1431
- const hasSubclassTransform = () => {
1432
- // If userTransform was provided in options, use that
1433
- if (userTransform) {
1434
- return false;
1604
+ });
1605
+ this._setupSideForwarding();
1606
+ }
1607
+ _setupSideForwarding() {
1608
+ if (this._sideForwardingCleanup) {
1609
+ this._sideForwardingCleanup();
1610
+ this._sideForwardingCleanup = null;
1611
+ }
1612
+ const registry = createListenerRegistry();
1613
+ registry.once(this._readable, "end", () => this.emit("end"));
1614
+ registry.add(this._readable, "error", err => this._emitErrorOnce(err));
1615
+ registry.once(this._writable, "finish", () => this.emit("finish"));
1616
+ registry.add(this._writable, "drain", () => this.emit("drain"));
1617
+ registry.add(this._writable, "error", err => this._emitErrorOnce(err));
1618
+ this._sideForwardingCleanup = () => registry.cleanup();
1619
+ }
1620
+ _scheduleEnd() {
1621
+ if (this._destroyed || this._errored) {
1622
+ return;
1623
+ }
1624
+ if (this._writable.writableEnded) {
1625
+ return;
1626
+ }
1627
+ if (this._endTimer) {
1628
+ clearTimeout(this._endTimer);
1629
+ }
1630
+ // Defer closing to allow writes triggered during 'data' callbacks.
1631
+ this._endTimer = setTimeout(() => {
1632
+ this._endTimer = null;
1633
+ if (this._destroyed || this._errored || this._writable.writableEnded) {
1634
+ return;
1435
1635
  }
1436
- // Check if _transform is overridden (not the base class no-op)
1437
- const proto = Object.getPrototypeOf(this);
1438
- return proto._transform !== Transform.prototype._transform;
1439
- };
1440
- const hasSubclassFlush = () => {
1441
- if (userFlush) {
1442
- return false;
1636
+ this._writable.end();
1637
+ }, 0);
1638
+ }
1639
+ _emitErrorOnce(err) {
1640
+ if (this._errored) {
1641
+ return;
1642
+ }
1643
+ this._errored = true;
1644
+ const error = err instanceof Error ? err : new Error(String(err));
1645
+ this.emit("error", error);
1646
+ if (!this._destroyed) {
1647
+ this._destroyed = true;
1648
+ this._readable.destroy(error);
1649
+ this._writable.destroy(error);
1650
+ queueMicrotask(() => this.emit("close"));
1651
+ }
1652
+ }
1653
+ _hasSubclassTransform() {
1654
+ if (this._transformImpl) {
1655
+ return false;
1656
+ }
1657
+ const proto = Object.getPrototypeOf(this);
1658
+ return proto._transform !== Transform.prototype._transform;
1659
+ }
1660
+ _hasSubclassFlush() {
1661
+ if (this._flushImpl) {
1662
+ return false;
1663
+ }
1664
+ const proto = Object.getPrototypeOf(this);
1665
+ return proto._flush !== Transform.prototype._flush;
1666
+ }
1667
+ async _runTransform(chunk) {
1668
+ if (this._destroyed || this._errored) {
1669
+ throw new Error(this._errored ? "Cannot write after stream errored" : "Cannot write after stream destroyed");
1670
+ }
1671
+ try {
1672
+ if (this._hasSubclassTransform()) {
1673
+ await new Promise((resolve, reject) => {
1674
+ this._transform(chunk, "utf8", (err, data) => {
1675
+ if (err) {
1676
+ reject(err);
1677
+ return;
1678
+ }
1679
+ if (data !== undefined) {
1680
+ this.push(data);
1681
+ }
1682
+ resolve();
1683
+ });
1684
+ });
1685
+ return;
1443
1686
  }
1444
- const proto = Object.getPrototypeOf(this);
1445
- return proto._flush !== Transform.prototype._flush;
1446
- };
1447
- this._stream = new TransformStream({
1448
- transform: async (chunk, controller) => {
1449
- // Skip processing if already errored
1450
- if (this._errored) {
1451
- return;
1452
- }
1453
- try {
1454
- // Set controller for push() to use
1455
- setController(controller);
1456
- // Check for subclass _transform override first
1457
- if (hasSubclassTransform()) {
1458
- // Call subclass _transform method (Node.js style)
1459
- // _transform signature is (chunk, encoding, callback)
1460
- await new Promise((resolve, reject) => {
1461
- this._transform(chunk, "utf8", (err, data) => {
1462
- if (err) {
1463
- reject(err);
1464
- }
1465
- else {
1466
- if (data !== undefined) {
1467
- controller.enqueue(data);
1468
- }
1469
- resolve();
1470
- }
1471
- });
1472
- });
1473
- }
1474
- else if (userTransform) {
1475
- const transformParamCount = userTransform.length;
1476
- if (transformParamCount >= 3) {
1477
- // Node.js style: transform(chunk, encoding, callback)
1478
- await new Promise((resolve, reject) => {
1479
- userTransform.call(getInstance(), chunk, "utf8", (err, data) => {
1480
- if (err) {
1481
- reject(err);
1482
- }
1483
- else {
1484
- if (data !== undefined) {
1485
- controller.enqueue(data);
1486
- }
1487
- resolve();
1488
- }
1489
- });
1490
- });
1687
+ const userTransform = this._transformImpl;
1688
+ if (!userTransform) {
1689
+ this.push(chunk);
1690
+ return;
1691
+ }
1692
+ const paramCount = userTransform.length;
1693
+ if (paramCount >= 3) {
1694
+ await new Promise((resolve, reject) => {
1695
+ userTransform.call(this, chunk, "utf8", (err, data) => {
1696
+ if (err) {
1697
+ reject(err);
1698
+ return;
1491
1699
  }
1492
- else if (transformParamCount === 2) {
1493
- await new Promise((resolve, reject) => {
1494
- userTransform.call(getInstance(), chunk, (err, data) => {
1495
- if (err) {
1496
- reject(err);
1497
- }
1498
- else {
1499
- if (data !== undefined) {
1500
- controller.enqueue(data);
1501
- }
1502
- resolve();
1503
- }
1504
- });
1505
- });
1700
+ if (data !== undefined) {
1701
+ this.push(data);
1506
1702
  }
1507
- else {
1508
- // Simple style: transform(chunk) => result
1509
- const result = userTransform.call(getInstance(), chunk);
1510
- if (result && typeof result.then === "function") {
1511
- const awaitedResult = await result;
1512
- if (awaitedResult !== undefined) {
1513
- controller.enqueue(awaitedResult);
1514
- }
1515
- }
1516
- else {
1517
- if (result !== undefined) {
1518
- controller.enqueue(result);
1519
- }
1520
- }
1703
+ resolve();
1704
+ });
1705
+ });
1706
+ return;
1707
+ }
1708
+ if (paramCount === 2) {
1709
+ await new Promise((resolve, reject) => {
1710
+ userTransform.call(this, chunk, (err, data) => {
1711
+ if (err) {
1712
+ reject(err);
1713
+ return;
1521
1714
  }
1522
- }
1523
- else {
1524
- // Default: pass through
1525
- controller.enqueue(chunk);
1526
- }
1527
- }
1528
- catch (err) {
1529
- controller.error(err);
1530
- emitEvent("error", err);
1531
- }
1532
- finally {
1533
- setController(null);
1715
+ if (data !== undefined) {
1716
+ this.push(data);
1717
+ }
1718
+ resolve();
1719
+ });
1720
+ });
1721
+ return;
1722
+ }
1723
+ const result = userTransform.call(this, chunk);
1724
+ if (result && typeof result.then === "function") {
1725
+ const awaited = await result;
1726
+ if (awaited !== undefined) {
1727
+ this.push(awaited);
1534
1728
  }
1535
- },
1536
- flush: async (controller) => {
1537
- try {
1538
- setController(controller);
1539
- // Check for subclass _flush override first
1540
- if (hasSubclassFlush()) {
1541
- await new Promise((resolve, reject) => {
1542
- this._flush((err, data) => {
1543
- if (err) {
1544
- reject(err);
1545
- }
1546
- else {
1547
- if (data !== undefined) {
1548
- controller.enqueue(data);
1549
- }
1550
- resolve();
1551
- }
1552
- });
1553
- });
1554
- }
1555
- else if (userFlush) {
1556
- const flushParamCount = userFlush.length;
1557
- if (flushParamCount >= 1) {
1558
- // Node.js style: flush(callback)
1559
- await new Promise((resolve, reject) => {
1560
- userFlush.call(getInstance(), (err, data) => {
1561
- if (err) {
1562
- reject(err);
1563
- }
1564
- else {
1565
- if (data !== undefined) {
1566
- controller.enqueue(data);
1567
- }
1568
- resolve();
1569
- }
1570
- });
1571
- });
1729
+ return;
1730
+ }
1731
+ if (result !== undefined) {
1732
+ this.push(result);
1733
+ }
1734
+ }
1735
+ catch (err) {
1736
+ this._emitErrorOnce(err);
1737
+ throw err;
1738
+ }
1739
+ }
1740
+ async _runFlush() {
1741
+ if (this._destroyed || this._errored) {
1742
+ return;
1743
+ }
1744
+ try {
1745
+ if (this._hasSubclassFlush()) {
1746
+ await new Promise((resolve, reject) => {
1747
+ this._flush((err, data) => {
1748
+ if (err) {
1749
+ reject(err);
1750
+ return;
1572
1751
  }
1573
- else {
1574
- // Simple style: flush() => result
1575
- const result = userFlush.call(getInstance());
1576
- if (result && typeof result.then === "function") {
1577
- const awaitedResult = await result;
1578
- if (awaitedResult !== undefined && awaitedResult !== null) {
1579
- controller.enqueue(awaitedResult);
1580
- }
1581
- }
1582
- else {
1583
- if (result !== undefined && result !== null) {
1584
- controller.enqueue(result);
1585
- }
1586
- }
1752
+ if (data !== undefined) {
1753
+ this.push(data);
1587
1754
  }
1588
- }
1589
- // No flush defined - nothing to do
1590
- }
1591
- catch (err) {
1592
- controller.error(err);
1593
- emitEvent("error", err);
1594
- }
1595
- finally {
1596
- setController(null);
1597
- }
1755
+ resolve();
1756
+ });
1757
+ });
1758
+ return;
1598
1759
  }
1599
- });
1600
- this._readable = new Readable({
1601
- stream: this._stream.readable,
1602
- objectMode: this.objectMode
1603
- });
1604
- this._writable = new Writable({
1605
- stream: this._stream.writable,
1606
- objectMode: this.objectMode
1607
- });
1608
- // Forward non-data events (data forwarding is lazy to avoid premature flowing)
1609
- this._readable.on("end", () => this.emit("end"));
1610
- // Only forward errors if not already errored (to prevent duplicate events)
1611
- this._readable.on("error", err => {
1612
- if (!this._errored) {
1613
- this._errored = true;
1614
- this.emit("error", err);
1760
+ const userFlush = this._flushImpl;
1761
+ if (!userFlush) {
1762
+ return;
1763
+ }
1764
+ const paramCount = userFlush.length;
1765
+ if (paramCount >= 1) {
1766
+ await new Promise((resolve, reject) => {
1767
+ userFlush.call(this, (err, data) => {
1768
+ if (err) {
1769
+ reject(err);
1770
+ return;
1771
+ }
1772
+ if (data !== undefined) {
1773
+ this.push(data);
1774
+ }
1775
+ resolve();
1776
+ });
1777
+ });
1778
+ return;
1615
1779
  }
1616
- });
1617
- this._writable.on("finish", () => this.emit("finish"));
1618
- this._writable.on("drain", () => this.emit("drain"));
1619
- // Only forward errors if not already errored (to prevent duplicate events)
1620
- this._writable.on("error", err => {
1621
- if (!this._errored) {
1622
- this._errored = true;
1623
- this.emit("error", err);
1780
+ const result = userFlush.call(this);
1781
+ if (result && typeof result.then === "function") {
1782
+ const awaited = await result;
1783
+ if (awaited !== undefined && awaited !== null) {
1784
+ this.push(awaited);
1785
+ }
1786
+ return;
1624
1787
  }
1625
- });
1788
+ if (result !== undefined && result !== null) {
1789
+ this.push(result);
1790
+ }
1791
+ }
1792
+ catch (err) {
1793
+ this._emitErrorOnce(err);
1794
+ throw err;
1795
+ }
1626
1796
  }
1627
1797
  /**
1628
- * Override on to start flowing when data listener is added
1798
+ * Override on() to lazily forward readable 'data' events.
1799
+ * Avoids starting flowing mode unless requested.
1629
1800
  */
1630
1801
  on(event, listener) {
1631
- // Set up data forwarding when first external data listener is added
1632
1802
  if (event === "data" && !this._dataForwardingSetup) {
1633
1803
  this._dataForwardingSetup = true;
1634
- this._readable.on("data", data => this.emit("data", data));
1635
- }
1636
- super.on(event, listener);
1637
- // When data listener is added, mark as having consumer
1638
- // and start the readable in flowing mode
1639
- if (event === "data") {
1640
- this._hasDataConsumer = true;
1641
- this._readable.resume();
1804
+ this._readable.on("data", chunk => this.emit("data", chunk));
1642
1805
  }
1643
- return this;
1806
+ return super.on(event, listener);
1644
1807
  }
1645
1808
  write(chunk, encodingOrCallback, callback) {
1646
1809
  const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
1647
- if (this._destroyed || this._errored) {
1648
- const err = new Error(this._errored ? "Cannot write after stream errored" : "Cannot write after stream destroyed");
1649
- queueMicrotask(() => this.emit("error", err));
1650
- cb?.(err);
1651
- return false;
1652
- }
1653
- // Ensure readable is being consumed to allow transform to execute
1654
- // This matches Node.js behavior where transform executes immediately on write
1655
- // Only auto-consume if no explicit consumer (data listener or pipe)
1656
- if (!this._readableConsuming && !this._hasDataConsumer) {
1657
- this._readableConsuming = true;
1658
- this._startAutoConsume();
1659
- }
1660
- // If end() was called but writable not yet closed, buffer the write
1661
- // This allows writes during data event handlers to be processed
1662
- if (this._endPending) {
1663
- this._pendingEndWrites.push({ chunk, callback: cb });
1664
- return true;
1810
+ // If end() has been requested, keep the close deferred as long as writes continue.
1811
+ if (this._ended && !this._writable.writableEnded) {
1812
+ this._scheduleEnd();
1665
1813
  }
1666
1814
  return this._writable.write(chunk, cb);
1667
1815
  }
1668
- /** @internal - auto-consume readable to allow transform to execute */
1669
- _startAutoConsume() {
1670
- this._autoConsumePromise = (async () => {
1671
- try {
1672
- for await (const chunk of this._readable) {
1673
- // Buffer the data for later retrieval
1674
- this._autoConsumedBuffer.push(chunk);
1675
- // Forward to any piped destinations
1676
- for (const dest of this._pipeDestinations) {
1677
- dest.write(chunk);
1678
- }
1679
- // Also emit data event for listeners
1680
- this.emit("data", chunk);
1681
- }
1682
- this._autoConsumeEnded = true;
1683
- // End all piped destinations
1684
- for (const dest of this._pipeDestinations) {
1685
- dest.end();
1686
- }
1687
- this.emit("end");
1688
- }
1689
- catch (err) {
1690
- this.emit("error", err);
1691
- }
1692
- })();
1693
- }
1694
1816
  end(chunkOrCallback, encodingOrCallback, callback) {
1695
1817
  if (this._ended) {
1696
1818
  return this;
1697
1819
  }
1698
1820
  this._ended = true;
1699
- this._endPending = true;
1700
1821
  const chunk = typeof chunkOrCallback === "function" ? undefined : chunkOrCallback;
1701
1822
  const cb = typeof chunkOrCallback === "function"
1702
1823
  ? chunkOrCallback
@@ -1709,18 +1830,7 @@ class Transform extends event_emitter_1.EventEmitter {
1709
1830
  if (chunk !== undefined) {
1710
1831
  this._writable.write(chunk);
1711
1832
  }
1712
- // Use setTimeout(0) instead of queueMicrotask to ensure all transform
1713
- // processing and data events complete before we close the writable.
1714
- // Microtasks run before the TransformStream processes data.
1715
- setTimeout(() => {
1716
- // Process any writes that occurred during data events
1717
- for (const { chunk: pendingChunk, callback } of this._pendingEndWrites) {
1718
- this._writable.write(pendingChunk, callback);
1719
- }
1720
- this._pendingEndWrites = [];
1721
- this._endPending = false;
1722
- this._writable.end();
1723
- }, 0);
1833
+ this._scheduleEnd();
1724
1834
  return this;
1725
1835
  }
1726
1836
  /**
@@ -1730,31 +1840,9 @@ class Transform extends event_emitter_1.EventEmitter {
1730
1840
  return this._readable.read(size);
1731
1841
  }
1732
1842
  /**
1733
- * Pipe to another stream (writable, transform, or duplex)
1843
+ * Pipe readable side to destination
1734
1844
  */
1735
1845
  pipe(destination) {
1736
- // Mark as having consumer to prevent new auto-consume from starting
1737
- this._hasDataConsumer = true;
1738
- // Get the writable target - handle both Transform (with internal _writable) and plain Writable
1739
- const dest = destination;
1740
- const target = dest?._writable ?? dest;
1741
- // Register destination for forwarding
1742
- this._pipeDestinations.push(target);
1743
- // If auto-consume is running or has run, we need to handle buffered data ourselves
1744
- if (this._readableConsuming) {
1745
- // Forward any buffered data from auto-consume to the destination
1746
- for (let i = 0; i < this._autoConsumedBuffer.length; i++) {
1747
- target.write(this._autoConsumedBuffer[i]);
1748
- }
1749
- // If auto-consume has ended, end the destination too
1750
- if (this._autoConsumeEnded) {
1751
- target.end();
1752
- }
1753
- // Don't call _readable.pipe() - auto-consume already consumed _readable
1754
- // Future data will be forwarded via the 'data' event listener below
1755
- return destination;
1756
- }
1757
- // No auto-consume running - use normal pipe through _readable
1758
1846
  return this._readable.pipe(destination);
1759
1847
  }
1760
1848
  /**
@@ -1792,6 +1880,10 @@ class Transform extends event_emitter_1.EventEmitter {
1792
1880
  return;
1793
1881
  }
1794
1882
  this._destroyed = true;
1883
+ if (this._sideForwardingCleanup) {
1884
+ this._sideForwardingCleanup();
1885
+ this._sideForwardingCleanup = null;
1886
+ }
1795
1887
  this._readable.destroy(error);
1796
1888
  this._writable.destroy(error);
1797
1889
  queueMicrotask(() => this.emit("close"));
@@ -1800,7 +1892,44 @@ class Transform extends event_emitter_1.EventEmitter {
1800
1892
  * Get the underlying Web TransformStream
1801
1893
  */
1802
1894
  get webStream() {
1803
- return this._stream;
1895
+ if (this._webStream) {
1896
+ return this._webStream;
1897
+ }
1898
+ // Web Streams interop layer.
1899
+ const iterator = this[Symbol.asyncIterator]();
1900
+ const readable = new ReadableStream({
1901
+ pull: async (controller) => {
1902
+ const { done, value } = await iterator.next();
1903
+ if (done) {
1904
+ controller.close();
1905
+ return;
1906
+ }
1907
+ controller.enqueue(value);
1908
+ },
1909
+ cancel: reason => {
1910
+ this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
1911
+ }
1912
+ });
1913
+ const writable = new WritableStream({
1914
+ write: chunk => new Promise((resolve, reject) => {
1915
+ this.write(chunk, err => {
1916
+ if (err) {
1917
+ reject(err);
1918
+ }
1919
+ else {
1920
+ resolve();
1921
+ }
1922
+ });
1923
+ }),
1924
+ close: () => new Promise(resolve => {
1925
+ this.end(() => resolve());
1926
+ }),
1927
+ abort: reason => {
1928
+ this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
1929
+ }
1930
+ });
1931
+ this._webStream = { readable, writable };
1932
+ return this._webStream;
1804
1933
  }
1805
1934
  get readable() {
1806
1935
  return this._readable.readable;
@@ -1842,19 +1971,6 @@ class Transform extends event_emitter_1.EventEmitter {
1842
1971
  * Async iterator support
1843
1972
  */
1844
1973
  async *[Symbol.asyncIterator]() {
1845
- // If auto-consume is running, wait for it to finish and use its buffer
1846
- if (this._autoConsumePromise) {
1847
- await this._autoConsumePromise;
1848
- // Yield all buffered data
1849
- while (this._autoConsumedBufferIndex < this._autoConsumedBuffer.length) {
1850
- yield this._autoConsumedBuffer[this._autoConsumedBufferIndex++];
1851
- }
1852
- // Reset when drained to avoid prefix growth
1853
- this._autoConsumedBuffer.length = 0;
1854
- this._autoConsumedBufferIndex = 0;
1855
- return;
1856
- }
1857
- // Otherwise delegate to readable's iterator
1858
1974
  yield* this._readable[Symbol.asyncIterator]();
1859
1975
  }
1860
1976
  // =========================================================================
@@ -1865,23 +1981,18 @@ class Transform extends event_emitter_1.EventEmitter {
1865
1981
  */
1866
1982
  static fromWeb(webStream, options) {
1867
1983
  const transform = new Transform(options);
1868
- // Connect the web stream - set the internal _stream property
1869
- transform._stream = webStream;
1984
+ transform._webStream = webStream;
1870
1985
  // Replace internal streams with the ones from the web stream
1871
1986
  const newReadable = Readable.fromWeb(webStream.readable, { objectMode: options?.objectMode });
1872
1987
  const newWritable = Writable.fromWeb(webStream.writable, { objectMode: options?.objectMode });
1873
- // Remove old event listeners before replacing
1874
- transform._readable.removeAllListeners();
1875
- transform._writable.removeAllListeners();
1988
+ if (transform._sideForwardingCleanup) {
1989
+ transform._sideForwardingCleanup();
1990
+ transform._sideForwardingCleanup = null;
1991
+ }
1876
1992
  transform._readable = newReadable;
1877
1993
  transform._writable = newWritable;
1878
- // Re-connect event forwarding
1879
- newReadable.on("data", (data) => transform.emit("data", data));
1880
- newReadable.on("end", () => transform.emit("end"));
1881
- newReadable.on("error", (err) => transform.emit("error", err));
1882
- newWritable.on("finish", () => transform.emit("finish"));
1883
- newWritable.on("drain", () => transform.emit("drain"));
1884
- newWritable.on("error", (err) => transform.emit("error", err));
1994
+ // Re-connect event forwarding (data forwarding remains lazy via Transform.on)
1995
+ transform._setupSideForwarding();
1885
1996
  return transform;
1886
1997
  }
1887
1998
  /**
@@ -1938,7 +2049,13 @@ class Duplex extends event_emitter_1.EventEmitter {
1938
2049
  callback();
1939
2050
  }
1940
2051
  });
1941
- readable.on("error", err => duplex.emit("error", err));
2052
+ const onError = (err) => {
2053
+ duplex.emit("error", err);
2054
+ };
2055
+ const cleanupError = addEmitterListener(readable, "error", onError);
2056
+ addEmitterListener(readable, "end", cleanupError, { once: true });
2057
+ addEmitterListener(readable, "close", cleanupError, { once: true });
2058
+ addEmitterListener(sink, "finish", cleanupError, { once: true });
1942
2059
  readable.pipe(sink);
1943
2060
  };
1944
2061
  // If it has readable and/or writable properties
@@ -1946,21 +2063,25 @@ class Duplex extends event_emitter_1.EventEmitter {
1946
2063
  source !== null &&
1947
2064
  "readable" in source &&
1948
2065
  "writable" in source) {
1949
- const duplex = new Duplex();
1950
2066
  const pair = source;
1951
- if (pair.readable) {
1952
- forwardReadableToDuplex(pair.readable, duplex);
1953
- }
1954
- if (pair.writable) {
1955
- return new Duplex({
1956
- objectMode: duplex.writableObjectMode,
1957
- write(chunk, encoding, callback) {
2067
+ // Create one duplex that can bridge both sides.
2068
+ // (Previous behavior returned a new writable-only Duplex and dropped the readable side.)
2069
+ const duplex = new Duplex({
2070
+ readableObjectMode: pair.readable?.readableObjectMode,
2071
+ writableObjectMode: pair.writable?.writableObjectMode,
2072
+ write: pair.writable
2073
+ ? (chunk, encoding, callback) => {
1958
2074
  pair.writable.write(chunk, encoding, callback);
1959
- },
1960
- final(callback) {
2075
+ }
2076
+ : undefined,
2077
+ final: pair.writable
2078
+ ? callback => {
1961
2079
  pair.writable.end(callback);
1962
2080
  }
1963
- });
2081
+ : undefined
2082
+ });
2083
+ if (pair.readable) {
2084
+ forwardReadableToDuplex(pair.readable, duplex);
1964
2085
  }
1965
2086
  return duplex;
1966
2087
  }
@@ -1998,9 +2119,22 @@ class Duplex extends event_emitter_1.EventEmitter {
1998
2119
  */
1999
2120
  static fromWeb(pair, options) {
2000
2121
  const duplex = new Duplex(options);
2001
- // Replace internal streams
2002
- duplex._readable = new Readable({ stream: pair.readable });
2003
- duplex._writable = new Writable({ stream: pair.writable });
2122
+ const newReadable = new Readable({
2123
+ stream: pair.readable,
2124
+ objectMode: duplex.readableObjectMode
2125
+ });
2126
+ const newWritable = new Writable({
2127
+ stream: pair.writable,
2128
+ objectMode: duplex.writableObjectMode
2129
+ });
2130
+ if (duplex._sideForwardingCleanup) {
2131
+ duplex._sideForwardingCleanup();
2132
+ duplex._sideForwardingCleanup = null;
2133
+ }
2134
+ duplex._readable = newReadable;
2135
+ duplex._writable = newWritable;
2136
+ // Re-wire event forwarding (data forwarding remains lazy via Duplex.on)
2137
+ duplex._setupSideForwarding();
2004
2138
  return duplex;
2005
2139
  }
2006
2140
  /**
@@ -2016,6 +2150,7 @@ class Duplex extends event_emitter_1.EventEmitter {
2016
2150
  super();
2017
2151
  // Track if we've already set up data forwarding
2018
2152
  this._dataForwardingSetup = false;
2153
+ this._sideForwardingCleanup = null;
2019
2154
  this.allowHalfOpen = options?.allowHalfOpen ?? true;
2020
2155
  // Support shorthand objectMode option
2021
2156
  const objectMode = options?.objectMode ?? false;
@@ -2032,23 +2167,31 @@ class Duplex extends event_emitter_1.EventEmitter {
2032
2167
  write: options?.write?.bind(this),
2033
2168
  final: options?.final?.bind(this)
2034
2169
  });
2170
+ this._setupSideForwarding();
2171
+ }
2172
+ _setupSideForwarding() {
2173
+ if (this._sideForwardingCleanup) {
2174
+ this._sideForwardingCleanup();
2175
+ this._sideForwardingCleanup = null;
2176
+ }
2177
+ const registry = createListenerRegistry();
2035
2178
  // Forward non-data events (data forwarding is lazy to avoid premature flowing)
2036
- this._readable.on("end", () => {
2179
+ registry.once(this._readable, "end", () => {
2037
2180
  this.emit("end");
2038
- // If not allowHalfOpen, end the writable side too
2039
2181
  if (!this.allowHalfOpen) {
2040
2182
  this._writable.end();
2041
2183
  }
2042
2184
  });
2043
- this._readable.on("error", err => this.emit("error", err));
2044
- this._writable.on("finish", () => this.emit("finish"));
2045
- this._writable.on("drain", () => this.emit("drain"));
2046
- this._writable.on("close", () => {
2047
- // If not allowHalfOpen, destroy the readable side too
2185
+ registry.add(this._readable, "error", err => this.emit("error", err));
2186
+ registry.add(this._writable, "error", err => this.emit("error", err));
2187
+ registry.once(this._writable, "finish", () => this.emit("finish"));
2188
+ registry.add(this._writable, "drain", () => this.emit("drain"));
2189
+ registry.once(this._writable, "close", () => {
2048
2190
  if (!this.allowHalfOpen && !this._readable.destroyed) {
2049
2191
  this._readable.destroy();
2050
2192
  }
2051
2193
  });
2194
+ this._sideForwardingCleanup = () => registry.cleanup();
2052
2195
  }
2053
2196
  /**
2054
2197
  * Override on() to set up data forwarding lazily
@@ -2167,6 +2310,10 @@ class Duplex extends event_emitter_1.EventEmitter {
2167
2310
  * Destroy both sides
2168
2311
  */
2169
2312
  destroy(error) {
2313
+ if (this._sideForwardingCleanup) {
2314
+ this._sideForwardingCleanup();
2315
+ this._sideForwardingCleanup = null;
2316
+ }
2170
2317
  this._readable.destroy(error);
2171
2318
  this._writable.destroy(error);
2172
2319
  return this;
@@ -2308,64 +2455,22 @@ class Collector extends Writable {
2308
2455
  }
2309
2456
  exports.Collector = Collector;
2310
2457
  // =============================================================================
2311
- // PullStream / BufferedStream / DataChunk helpers
2312
- // =============================================================================
2313
- class PullStream extends pull_stream_1.PullStream {
2314
- // Keep constructor signature aligned with streams.browser.ts public API
2315
- constructor(options) {
2316
- super(options);
2317
- }
2318
- }
2319
- exports.PullStream = PullStream;
2320
- class StringChunk extends buffered_stream_1.StringChunk {
2321
- }
2322
- exports.StringChunk = StringChunk;
2323
- class BufferChunk extends buffered_stream_1.BufferChunk {
2324
- }
2325
- exports.BufferChunk = BufferChunk;
2326
- class BufferedStream extends buffered_stream_1.BufferedStream {
2327
- constructor(options) {
2328
- super(options);
2329
- }
2330
- }
2331
- exports.BufferedStream = BufferedStream;
2332
- // =============================================================================
2333
2458
  // Stream Creation Functions
2334
2459
  // =============================================================================
2335
2460
  /**
2336
2461
  * Create a readable stream with custom read implementation
2337
2462
  */
2338
2463
  function createReadable(options) {
2339
- const readable = new Readable(options);
2340
- // Override read behavior if provided
2341
- if (options?.read) {
2342
- const originalRead = readable.read.bind(readable);
2343
- readable.read = function (size) {
2344
- options.read(size ?? 16384);
2345
- return originalRead(size);
2346
- };
2347
- }
2348
- return readable;
2464
+ // Readable already supports Node-style `read()` via the constructor option.
2465
+ // Keep this helper minimal to avoid accidental double-read behavior.
2466
+ return new Readable(options);
2349
2467
  }
2350
2468
  /**
2351
2469
  * Create a readable stream from an async iterable
2352
2470
  */
2353
2471
  function createReadableFromAsyncIterable(iterable, options) {
2354
2472
  const readable = new Readable({ ...options, objectMode: options?.objectMode ?? true });
2355
- (async () => {
2356
- try {
2357
- for await (const chunk of iterable) {
2358
- if (!readable.push(chunk)) {
2359
- // Backpressure - wait a bit
2360
- await new Promise(resolve => setTimeout(resolve, 0));
2361
- }
2362
- }
2363
- readable.push(null);
2364
- }
2365
- catch (err) {
2366
- readable.destroy(err);
2367
- }
2368
- })();
2473
+ pumpAsyncIterableToReadable(readable, iterable);
2369
2474
  return readable;
2370
2475
  }
2371
2476
  /**
@@ -2394,38 +2499,8 @@ function createReadableFromArray(data, options) {
2394
2499
  * Create a writable stream with custom write implementation
2395
2500
  */
2396
2501
  function createWritable(options) {
2397
- // Create a custom WritableStream with user's handlers
2398
- const stream = new WritableStream({
2399
- write: async (chunk) => {
2400
- if (options?.write) {
2401
- return new Promise((resolve, reject) => {
2402
- options.write(chunk, "utf8", err => {
2403
- if (err) {
2404
- reject(err);
2405
- }
2406
- else {
2407
- resolve();
2408
- }
2409
- });
2410
- });
2411
- }
2412
- },
2413
- close: async () => {
2414
- if (options?.final) {
2415
- return new Promise((resolve, reject) => {
2416
- options.final(err => {
2417
- if (err) {
2418
- reject(err);
2419
- }
2420
- else {
2421
- resolve();
2422
- }
2423
- });
2424
- });
2425
- }
2426
- }
2427
- });
2428
- return new Writable({ ...options, stream });
2502
+ // Writable already supports Node-style `write()` / `final()` via the constructor.
2503
+ return new Writable(options);
2429
2504
  }
2430
2505
  /**
2431
2506
  * Create a transform stream from a transform function
@@ -2453,28 +2528,14 @@ function createPassThrough(options) {
2453
2528
  * Create a pull stream
2454
2529
  */
2455
2530
  function createPullStream(options) {
2456
- return new PullStream(options);
2531
+ return new pull_stream_1.PullStream(options);
2457
2532
  }
2458
2533
  /**
2459
2534
  * Create a buffered stream
2460
2535
  */
2461
2536
  function createBufferedStream(options) {
2462
- return new BufferedStream(options);
2537
+ return new buffered_stream_1.BufferedStream(options);
2463
2538
  }
2464
- const isReadableStream = (value) => !!value && typeof value === "object" && typeof value.getReader === "function";
2465
- const isAsyncIterable = (value) => {
2466
- if (!value || (typeof value !== "object" && typeof value !== "function")) {
2467
- return false;
2468
- }
2469
- return typeof value[Symbol.asyncIterator] === "function";
2470
- };
2471
- const isWritableStream = (value) => !!value && typeof value === "object" && typeof value.getWriter === "function";
2472
- const isTransformStream = (value) => !!value &&
2473
- typeof value === "object" &&
2474
- !!value.readable &&
2475
- !!value.writable &&
2476
- isReadableStream(value.readable) &&
2477
- isWritableStream(value.writable);
2478
2539
  const isPipelineOptions = (value) => {
2479
2540
  if (!value || typeof value !== "object") {
2480
2541
  return false;
@@ -2499,13 +2560,13 @@ const toBrowserPipelineStream = (stream) => {
2499
2560
  stream instanceof Duplex) {
2500
2561
  return stream;
2501
2562
  }
2502
- if (isTransformStream(stream)) {
2563
+ if ((0, type_guards_1.isTransformStream)(stream)) {
2503
2564
  return Transform.fromWeb(stream);
2504
2565
  }
2505
- if (isReadableStream(stream)) {
2566
+ if ((0, type_guards_1.isReadableStream)(stream)) {
2506
2567
  return Readable.fromWeb(stream);
2507
2568
  }
2508
- if (isWritableStream(stream)) {
2569
+ if ((0, type_guards_1.isWritableStream)(stream)) {
2509
2570
  return Writable.fromWeb(stream);
2510
2571
  }
2511
2572
  return stream;
@@ -2560,11 +2621,17 @@ function pipeline(...args) {
2560
2621
  const transforms = normalized.slice(1, -1);
2561
2622
  let completed = false;
2562
2623
  const allStreams = [source, ...transforms, destination];
2563
- const cleanup = (error) => {
2624
+ const registry = createListenerRegistry();
2625
+ let onAbort;
2626
+ const cleanupWithSignal = (error) => {
2564
2627
  if (completed) {
2565
2628
  return;
2566
2629
  }
2567
2630
  completed = true;
2631
+ registry.cleanup();
2632
+ if (onAbort && options.signal) {
2633
+ options.signal.removeEventListener("abort", onAbort);
2634
+ }
2568
2635
  // Destroy all streams on error
2569
2636
  if (error) {
2570
2637
  for (const stream of allStreams) {
@@ -2581,12 +2648,11 @@ function pipeline(...args) {
2581
2648
  // Handle abort signal
2582
2649
  if (options.signal) {
2583
2650
  if (options.signal.aborted) {
2584
- cleanup(new Error("Pipeline aborted"));
2651
+ cleanupWithSignal(new Error("Pipeline aborted"));
2585
2652
  return;
2586
2653
  }
2587
- options.signal.addEventListener("abort", () => {
2588
- cleanup(new Error("Pipeline aborted"));
2589
- });
2654
+ onAbort = () => cleanupWithSignal(new Error("Pipeline aborted"));
2655
+ options.signal.addEventListener("abort", onAbort);
2590
2656
  }
2591
2657
  // Chain the streams
2592
2658
  let current = source;
@@ -2600,13 +2666,35 @@ function pipeline(...args) {
2600
2666
  }
2601
2667
  else {
2602
2668
  // Don't end destination
2603
- current.on("data", chunk => destination.write(chunk));
2669
+ let paused = false;
2670
+ let waitingForDrain = false;
2671
+ const onDrain = () => {
2672
+ waitingForDrain = false;
2673
+ if (paused && typeof current.resume === "function") {
2674
+ paused = false;
2675
+ current.resume();
2676
+ }
2677
+ };
2678
+ const onData = (chunk) => {
2679
+ const ok = destination.write(chunk);
2680
+ if (!ok && !waitingForDrain) {
2681
+ waitingForDrain = true;
2682
+ if (!paused && typeof current.pause === "function") {
2683
+ paused = true;
2684
+ current.pause();
2685
+ }
2686
+ registry.once(destination, "drain", onDrain);
2687
+ }
2688
+ };
2689
+ const onEnd = () => cleanupWithSignal();
2690
+ registry.add(current, "data", onData);
2691
+ registry.once(current, "end", onEnd);
2604
2692
  }
2605
2693
  // Handle completion
2606
- destination.on("finish", () => cleanup());
2694
+ registry.once(destination, "finish", () => cleanupWithSignal());
2607
2695
  // Handle errors on all streams
2608
2696
  for (const stream of allStreams) {
2609
- stream.on("error", (err) => cleanup(err));
2697
+ registry.once(stream, "error", (err) => cleanupWithSignal(err));
2610
2698
  }
2611
2699
  });
2612
2700
  // If callback provided, use it
@@ -2646,11 +2734,20 @@ function finished(stream, optionsOrCallback, callback) {
2646
2734
  const promise = new Promise((resolve, reject) => {
2647
2735
  const normalizedStream = toBrowserPipelineStream(stream);
2648
2736
  let resolved = false;
2737
+ const registry = createListenerRegistry();
2738
+ let onAbort;
2739
+ const cleanup = () => {
2740
+ registry.cleanup();
2741
+ if (onAbort && options.signal) {
2742
+ options.signal.removeEventListener("abort", onAbort);
2743
+ }
2744
+ };
2649
2745
  const done = (err) => {
2650
2746
  if (resolved) {
2651
2747
  return;
2652
2748
  }
2653
2749
  resolved = true;
2750
+ cleanup();
2654
2751
  if (err && !options.error) {
2655
2752
  reject(err);
2656
2753
  }
@@ -2664,9 +2761,8 @@ function finished(stream, optionsOrCallback, callback) {
2664
2761
  done(new Error("Aborted"));
2665
2762
  return;
2666
2763
  }
2667
- options.signal.addEventListener("abort", () => {
2668
- done(new Error("Aborted"));
2669
- });
2764
+ onAbort = () => done(new Error("Aborted"));
2765
+ options.signal.addEventListener("abort", onAbort);
2670
2766
  }
2671
2767
  const checkReadable = options.readable !== false;
2672
2768
  const checkWritable = options.writable !== false;
@@ -2681,13 +2777,13 @@ function finished(stream, optionsOrCallback, callback) {
2681
2777
  }
2682
2778
  // Listen for events
2683
2779
  if (checkWritable) {
2684
- normalizedStream.on("finish", () => done());
2780
+ registry.once(normalizedStream, "finish", () => done());
2685
2781
  }
2686
2782
  if (checkReadable) {
2687
- normalizedStream.on("end", () => done());
2783
+ registry.once(normalizedStream, "end", () => done());
2688
2784
  }
2689
- normalizedStream.on("error", (err) => done(err));
2690
- normalizedStream.on("close", () => done());
2785
+ registry.once(normalizedStream, "error", (err) => done(err));
2786
+ registry.once(normalizedStream, "close", () => done());
2691
2787
  });
2692
2788
  // If callback provided, use it
2693
2789
  if (cb) {
@@ -2709,38 +2805,8 @@ async function streamToPromise(stream) {
2709
2805
  * (Browser equivalent of Node.js streamToBuffer)
2710
2806
  */
2711
2807
  async function streamToUint8Array(stream) {
2712
- let iterable;
2713
- if (isReadableStream(stream)) {
2714
- iterable = Readable.fromWeb(stream);
2715
- }
2716
- else if (isAsyncIterable(stream)) {
2717
- iterable = stream;
2718
- }
2719
- else {
2720
- throw new Error("streamToUint8Array: unsupported stream type");
2721
- }
2722
- const chunks = [];
2723
- let totalLength = 0;
2724
- for await (const chunk of iterable) {
2725
- chunks.push(chunk);
2726
- totalLength += chunk.length;
2727
- }
2728
- // Fast paths
2729
- const len = chunks.length;
2730
- if (len === 0) {
2731
- return new Uint8Array(0);
2732
- }
2733
- if (len === 1) {
2734
- return chunks[0];
2735
- }
2736
- // Use precalculated total length
2737
- const result = new Uint8Array(totalLength);
2738
- let offset = 0;
2739
- for (let i = 0; i < len; i++) {
2740
- result.set(chunks[i], offset);
2741
- offset += chunks[i].length;
2742
- }
2743
- return result;
2808
+ const [chunks, totalLength] = await collectStreamChunks(stream);
2809
+ return (0, shared_1.concatUint8Arrays)(chunks, totalLength);
2744
2810
  }
2745
2811
  /**
2746
2812
  * Alias for streamToUint8Array (Node.js compatibility)
@@ -2750,23 +2816,16 @@ exports.streamToBuffer = streamToUint8Array;
2750
2816
  * Collect all data from a readable stream into a string
2751
2817
  */
2752
2818
  async function streamToString(stream, encoding) {
2753
- const buffer = await streamToUint8Array(stream);
2754
- return (0, shared_1.getTextDecoder)(encoding).decode(buffer);
2819
+ const [chunks, totalLength] = await collectStreamChunks(stream);
2820
+ const combined = (0, shared_1.concatUint8Arrays)(chunks, totalLength);
2821
+ const decoder = encoding ? (0, shared_1.getTextDecoder)(encoding) : shared_1.textDecoder;
2822
+ return decoder.decode(combined);
2755
2823
  }
2756
2824
  /**
2757
2825
  * Drain a stream (consume all data without processing)
2758
2826
  */
2759
2827
  async function drainStream(stream) {
2760
- let iterable;
2761
- if (isReadableStream(stream)) {
2762
- iterable = Readable.fromWeb(stream);
2763
- }
2764
- else if (isAsyncIterable(stream)) {
2765
- iterable = stream;
2766
- }
2767
- else {
2768
- throw new Error("drainStream: unsupported stream type");
2769
- }
2828
+ const iterable = toReadableAsyncIterable(stream, "drainStream");
2770
2829
  for await (const _chunk of iterable) {
2771
2830
  // Consume data
2772
2831
  }
@@ -2839,14 +2898,19 @@ function addAbortSignal(signal, stream) {
2839
2898
  stream.destroy(new Error("Aborted"));
2840
2899
  return stream;
2841
2900
  }
2901
+ const cleanup = () => {
2902
+ signal.removeEventListener("abort", onAbort);
2903
+ removeEmitterListener(stream, "close", onClose);
2904
+ };
2842
2905
  const onAbort = () => {
2906
+ cleanup();
2843
2907
  stream.destroy(new Error("Aborted"));
2844
2908
  };
2845
- signal.addEventListener("abort", onAbort, { once: true });
2846
- // Clean up when stream is destroyed
2847
- stream.on("close", () => {
2848
- signal.removeEventListener("abort", onAbort);
2849
- });
2909
+ const onClose = () => {
2910
+ cleanup();
2911
+ };
2912
+ signal.addEventListener("abort", onAbort);
2913
+ addEmitterListener(stream, "close", onClose, { once: true });
2850
2914
  return stream;
2851
2915
  }
2852
2916
  /**
@@ -2855,60 +2919,68 @@ function addAbortSignal(signal, stream) {
2855
2919
  function createDuplex(options) {
2856
2920
  const readableObjectMode = options?.readableObjectMode ?? options?.objectMode;
2857
2921
  const writableObjectMode = options?.writableObjectMode ?? options?.objectMode;
2922
+ const underlyingWritable = options?.writable;
2858
2923
  const duplex = new Duplex({
2859
2924
  allowHalfOpen: options?.allowHalfOpen,
2860
2925
  readableHighWaterMark: options?.readableHighWaterMark,
2861
2926
  writableHighWaterMark: options?.writableHighWaterMark,
2862
2927
  readableObjectMode,
2863
- writableObjectMode
2928
+ writableObjectMode,
2929
+ read: options?.read,
2930
+ write: options?.write ??
2931
+ (underlyingWritable
2932
+ ? (chunk, encoding, callback) => {
2933
+ if (typeof underlyingWritable.write === "function") {
2934
+ underlyingWritable.write(chunk, encoding, callback);
2935
+ return;
2936
+ }
2937
+ // Best-effort sync sink
2938
+ try {
2939
+ underlyingWritable.write?.(chunk);
2940
+ callback(null);
2941
+ }
2942
+ catch (err) {
2943
+ callback(err);
2944
+ }
2945
+ }
2946
+ : undefined),
2947
+ final: options?.final ??
2948
+ (underlyingWritable
2949
+ ? (callback) => {
2950
+ if (typeof underlyingWritable.end === "function") {
2951
+ underlyingWritable.end((err) => callback(err ?? null));
2952
+ }
2953
+ else {
2954
+ underlyingWritable.end?.();
2955
+ callback(null);
2956
+ }
2957
+ }
2958
+ : undefined)
2864
2959
  });
2865
- // If custom readable/writable provided, pipe them
2960
+ // If an underlying readable is provided, forward it into the duplex readable side.
2866
2961
  if (options?.readable) {
2867
2962
  const readable = options.readable;
2868
- readable.on?.("data", (chunk) => duplex.push(chunk));
2869
- readable.on?.("end", () => duplex.push(null));
2870
- readable.on?.("error", (err) => duplex.destroy(err));
2871
- }
2872
- if (options?.writable) {
2873
- const writable = options.writable;
2874
- duplex.on("data", (chunk) => writable.write?.(chunk));
2875
- duplex.on("finish", () => writable.end?.());
2876
- }
2877
- // If custom read/write/final provided, override methods
2878
- if (options?.write) {
2879
- const _originalWrite = duplex.write.bind(duplex); // Keep bound reference for potential future use
2880
- duplex.write = function (chunk, encodingOrCallback, callback) {
2881
- const encoding = typeof encodingOrCallback === "string" ? encodingOrCallback : "utf8";
2882
- const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : (callback ?? (() => { }));
2883
- options.write.call(duplex, chunk, encoding, cb);
2884
- return true;
2885
- };
2886
- }
2887
- if (options?.final) {
2888
- const originalEnd = duplex.end.bind(duplex);
2889
- duplex.end = function (chunkOrCallback, encodingOrCallback, callback) {
2890
- const cb = typeof chunkOrCallback === "function"
2891
- ? chunkOrCallback
2892
- : typeof encodingOrCallback === "function"
2893
- ? encodingOrCallback
2894
- : (callback ?? (() => { }));
2895
- if (chunkOrCallback !== undefined && typeof chunkOrCallback !== "function") {
2896
- duplex.write(chunkOrCallback);
2897
- }
2898
- // Call custom final handler
2899
- options.final.call(duplex, (err) => {
2900
- if (err) {
2901
- duplex.emit("error", err);
2902
- }
2903
- else {
2904
- duplex.emit("finish");
2905
- }
2906
- // Call original end to properly close writable side
2907
- originalEnd();
2908
- cb();
2909
- });
2910
- return duplex;
2911
- };
2963
+ const sink = new Writable({
2964
+ objectMode: duplex.readableObjectMode,
2965
+ write(chunk, _encoding, callback) {
2966
+ duplex.push(chunk);
2967
+ callback(null);
2968
+ },
2969
+ final(callback) {
2970
+ duplex.push(null);
2971
+ callback(null);
2972
+ }
2973
+ });
2974
+ if (typeof readable?.on === "function") {
2975
+ const onError = (err) => {
2976
+ duplex.destroy(err);
2977
+ };
2978
+ const cleanupError = addEmitterListener(readable, "error", onError);
2979
+ addEmitterListener(readable, "end", cleanupError, { once: true });
2980
+ addEmitterListener(readable, "close", cleanupError, { once: true });
2981
+ addEmitterListener(sink, "finish", cleanupError, { once: true });
2982
+ }
2983
+ readable.pipe?.(sink);
2912
2984
  }
2913
2985
  if (options?.destroy) {
2914
2986
  const originalDestroy = duplex.destroy.bind(duplex);
@@ -2932,20 +3004,7 @@ function createDuplex(options) {
2932
3004
  */
2933
3005
  function createReadableFromGenerator(generator, options) {
2934
3006
  const readable = new Readable({ ...options, objectMode: options?.objectMode ?? true });
2935
- (async () => {
2936
- try {
2937
- for await (const chunk of generator()) {
2938
- if (!readable.push(chunk)) {
2939
- // Backpressure
2940
- await new Promise(resolve => setTimeout(resolve, 0));
2941
- }
2942
- }
2943
- readable.push(null);
2944
- }
2945
- catch (err) {
2946
- readable.destroy(err);
2947
- }
2948
- })();
3007
+ pumpAsyncIterableToReadable(readable, generator());
2949
3008
  return readable;
2950
3009
  }
2951
3010
  /**
@@ -2975,8 +3034,8 @@ function compose(...transforms) {
2975
3034
  transform: chunk => chunk
2976
3035
  });
2977
3036
  }
2978
- const isNativeTransform = (stream) => stream instanceof Transform;
2979
- if (len === 1 && isNativeTransform(transforms[0])) {
3037
+ // Preserve identity: compose(single) returns the same transform.
3038
+ if (len === 1) {
2980
3039
  return transforms[0];
2981
3040
  }
2982
3041
  // Chain the transforms: first → second → ... → last
@@ -2986,74 +3045,118 @@ function compose(...transforms) {
2986
3045
  for (let i = 0; i < len - 1; i++) {
2987
3046
  transforms[i].pipe(transforms[i + 1]);
2988
3047
  }
2989
- class ComposedTransform extends Transform {
2990
- constructor() {
2991
- super(...arguments);
2992
- this._dataForwarding = false;
2993
- this._endForwarding = false;
3048
+ // A lightweight Transform wrapper that delegates:
3049
+ // - writable side to `first`
3050
+ // - readable side to `last`
3051
+ // It forwards relevant events lazily to avoid per-chunk overhead when unused.
3052
+ const composed = new Transform({
3053
+ objectMode: first?.objectMode ?? true,
3054
+ transform: chunk => chunk
3055
+ });
3056
+ const registry = createListenerRegistry();
3057
+ // Always forward errors; they are critical for pipeline semantics.
3058
+ for (const t of transforms) {
3059
+ registry.add(t, "error", (err) => composed.emit("error", err));
3060
+ }
3061
+ // Forward writable-side backpressure/completion events from `first`.
3062
+ registry.add(first, "drain", () => composed.emit("drain"));
3063
+ registry.once(first, "finish", () => composed.emit("finish"));
3064
+ // Forward readable-side events from `last` lazily.
3065
+ let forwardData = false;
3066
+ let forwardEnd = false;
3067
+ let forwardReadable = false;
3068
+ const ensureDataForwarding = () => {
3069
+ if (forwardData) {
3070
+ return;
2994
3071
  }
2995
- on(event, listener) {
2996
- if (event === "data" && !this._dataForwarding) {
2997
- this._dataForwarding = true;
2998
- last.on("data", (chunk) => this.emit("data", chunk));
2999
- }
3000
- if (event === "end" && !this._endForwarding) {
3001
- this._endForwarding = true;
3002
- last.on("end", () => this.emit("end"));
3003
- }
3004
- return super.on(event, listener);
3072
+ forwardData = true;
3073
+ registry.add(last, "data", (chunk) => composed.emit("data", chunk));
3074
+ };
3075
+ const ensureEndForwarding = () => {
3076
+ if (forwardEnd) {
3077
+ return;
3005
3078
  }
3006
- write(chunk, encodingOrCallback, callback) {
3007
- if (typeof encodingOrCallback === "function") {
3008
- return first.write(chunk, encodingOrCallback);
3009
- }
3010
- return first.write(chunk, encodingOrCallback, callback);
3079
+ forwardEnd = true;
3080
+ registry.once(last, "end", () => composed.emit("end"));
3081
+ };
3082
+ const ensureReadableForwarding = () => {
3083
+ if (forwardReadable) {
3084
+ return;
3011
3085
  }
3012
- end(chunkOrCallback, encodingOrCallback, callback) {
3013
- if (typeof chunkOrCallback === "function") {
3014
- first.end(chunkOrCallback);
3015
- return this;
3016
- }
3017
- if (typeof encodingOrCallback === "function") {
3018
- first.end(chunkOrCallback, encodingOrCallback);
3019
- return this;
3020
- }
3021
- first.end(chunkOrCallback, encodingOrCallback, callback);
3022
- return this;
3086
+ forwardReadable = true;
3087
+ registry.add(last, "readable", () => composed.emit("readable"));
3088
+ };
3089
+ const originalOn = composed.on.bind(composed);
3090
+ const originalOnce = composed.once.bind(composed);
3091
+ composed.on = (event, listener) => {
3092
+ if (event === "data") {
3093
+ ensureDataForwarding();
3023
3094
  }
3024
- pipe(destination) {
3025
- return last.pipe(destination);
3095
+ else if (event === "end") {
3096
+ ensureEndForwarding();
3026
3097
  }
3027
- destroy(error) {
3028
- for (const t of transforms) {
3029
- t.destroy(error);
3030
- }
3031
- super.destroy(error);
3098
+ else if (event === "readable") {
3099
+ ensureReadableForwarding();
3100
+ }
3101
+ return originalOn(event, listener);
3102
+ };
3103
+ composed.once = (event, listener) => {
3104
+ if (event === "data") {
3105
+ ensureDataForwarding();
3032
3106
  }
3033
- read(size) {
3034
- return typeof last.read === "function" ? last.read(size) : null;
3107
+ else if (event === "end") {
3108
+ ensureEndForwarding();
3035
3109
  }
3036
- async *[Symbol.asyncIterator]() {
3037
- const it = last?.[Symbol.asyncIterator]?.();
3038
- if (it) {
3039
- for await (const chunk of it) {
3040
- yield chunk;
3041
- }
3042
- return;
3110
+ else if (event === "readable") {
3111
+ ensureReadableForwarding();
3112
+ }
3113
+ return originalOnce(event, listener);
3114
+ };
3115
+ // Delegate core stream methods
3116
+ const firstAny = first;
3117
+ const lastAny = last;
3118
+ composed.write = (chunk, encodingOrCallback, callback) => {
3119
+ if (typeof encodingOrCallback === "function") {
3120
+ return firstAny.write(chunk, encodingOrCallback);
3121
+ }
3122
+ return firstAny.write(chunk, encodingOrCallback, callback);
3123
+ };
3124
+ composed.end = (chunkOrCallback, encodingOrCallback, callback) => {
3125
+ if (typeof chunkOrCallback === "function") {
3126
+ firstAny.end(chunkOrCallback);
3127
+ return composed;
3128
+ }
3129
+ if (typeof encodingOrCallback === "function") {
3130
+ firstAny.end(chunkOrCallback, encodingOrCallback);
3131
+ return composed;
3132
+ }
3133
+ firstAny.end(chunkOrCallback, encodingOrCallback, callback);
3134
+ return composed;
3135
+ };
3136
+ composed.pipe = (destination) => {
3137
+ return lastAny.pipe(destination);
3138
+ };
3139
+ composed.read = (size) => {
3140
+ return typeof lastAny.read === "function" ? lastAny.read(size) : null;
3141
+ };
3142
+ composed[Symbol.asyncIterator] = async function* () {
3143
+ const it = lastAny?.[Symbol.asyncIterator]?.();
3144
+ if (it) {
3145
+ for await (const chunk of it) {
3146
+ yield chunk;
3043
3147
  }
3044
- yield* super[Symbol.asyncIterator]();
3148
+ return;
3045
3149
  }
3046
- }
3047
- const composed = new ComposedTransform({
3048
- objectMode: first?.objectMode ?? true,
3049
- transform: chunk => chunk
3150
+ yield* Transform.prototype[Symbol.asyncIterator].call(composed);
3151
+ };
3152
+ const originalDestroy = composed.destroy.bind(composed);
3153
+ composed.destroy = ((error) => {
3154
+ registry.cleanup();
3155
+ for (const t of transforms) {
3156
+ t.destroy(error);
3157
+ }
3158
+ originalDestroy(error);
3050
3159
  });
3051
- // Forward errors from any transform
3052
- for (const t of transforms) {
3053
- t.on("error", (err) => {
3054
- composed.emit("error", err);
3055
- });
3056
- }
3057
3160
  // Reflect underlying readability/writability like the previous duck-typed wrapper
3058
3161
  Object.defineProperty(composed, "readable", {
3059
3162
  get: () => last.readable
@@ -3299,77 +3402,54 @@ function duplexPair(options) {
3299
3402
  async function collectStreamChunks(stream) {
3300
3403
  const chunks = [];
3301
3404
  let totalLength = 0;
3302
- let iterable;
3303
- if (isReadableStream(stream)) {
3304
- iterable = Readable.fromWeb(stream);
3305
- }
3306
- else if (isAsyncIterable(stream)) {
3307
- iterable = stream;
3308
- }
3309
- else {
3310
- throw new Error("collectStreamChunks: unsupported stream type");
3311
- }
3405
+ const iterable = toReadableAsyncIterable(stream, "collectStreamChunks");
3312
3406
  for await (const chunk of iterable) {
3313
3407
  chunks.push(chunk);
3314
3408
  totalLength += chunk.length;
3315
3409
  }
3316
- return { chunks, totalLength };
3410
+ return [chunks, totalLength];
3317
3411
  }
3318
- // Helper to concatenate with known length (faster)
3319
- function concatWithLength(chunks, totalLength) {
3320
- const len = chunks.length;
3321
- if (len === 0) {
3322
- return new Uint8Array(0);
3323
- }
3324
- if (len === 1) {
3325
- return chunks[0];
3412
+ function toReadableAsyncIterable(stream, name) {
3413
+ if ((0, type_guards_1.isReadableStream)(stream)) {
3414
+ return Readable.fromWeb(stream);
3326
3415
  }
3327
- const result = new Uint8Array(totalLength);
3328
- let offset = 0;
3329
- for (let i = 0; i < len; i++) {
3330
- result.set(chunks[i], offset);
3331
- offset += chunks[i].length;
3416
+ if ((0, type_guards_1.isAsyncIterable)(stream)) {
3417
+ return stream;
3332
3418
  }
3333
- return result;
3419
+ throw new Error(`${name}: unsupported stream type`);
3334
3420
  }
3335
3421
  exports.consumers = {
3336
3422
  /**
3337
3423
  * Consume entire stream as ArrayBuffer
3338
3424
  */
3339
3425
  async arrayBuffer(stream) {
3340
- const { chunks, totalLength } = await collectStreamChunks(stream);
3341
- const combined = concatWithLength(chunks, totalLength);
3342
- return combined.buffer.slice(combined.byteOffset, combined.byteOffset + combined.byteLength);
3426
+ const bytes = await streamToUint8Array(stream);
3427
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
3343
3428
  },
3344
3429
  /**
3345
3430
  * Consume entire stream as Blob
3346
3431
  */
3347
3432
  async blob(stream, options) {
3348
- const { chunks } = await collectStreamChunks(stream);
3433
+ const [chunks] = await collectStreamChunks(stream);
3349
3434
  return new Blob(chunks, options);
3350
3435
  },
3351
3436
  /**
3352
3437
  * Consume entire stream as Buffer (Uint8Array in browser)
3353
3438
  */
3354
3439
  async buffer(stream) {
3355
- const { chunks, totalLength } = await collectStreamChunks(stream);
3356
- return concatWithLength(chunks, totalLength);
3440
+ return streamToUint8Array(stream);
3357
3441
  },
3358
3442
  /**
3359
3443
  * Consume entire stream as JSON
3360
3444
  */
3361
3445
  async json(stream) {
3362
- const text = await exports.consumers.text(stream);
3363
- return JSON.parse(text);
3446
+ return JSON.parse(await streamToString(stream));
3364
3447
  },
3365
3448
  /**
3366
3449
  * Consume entire stream as text
3367
3450
  */
3368
3451
  async text(stream, encoding) {
3369
- const { chunks, totalLength } = await collectStreamChunks(stream);
3370
- const combined = concatWithLength(chunks, totalLength);
3371
- const decoder = encoding ? (0, shared_1.getTextDecoder)(encoding) : shared_1.textDecoder;
3372
- return decoder.decode(combined);
3452
+ return streamToString(stream, encoding);
3373
3453
  }
3374
3454
  };
3375
3455
  // =============================================================================