@yanglaofish/fishtools 0.5.2 → 0.6.0

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 (871) hide show
  1. package/README.md +24 -12
  2. package/manual/README.md +24 -12
  3. package/manual/docs/deployment.md +3 -3
  4. package/manual/docs/examples/action-plugin/package.json +1 -1
  5. package/manual/docs/modules.md +2 -0
  6. package/manual/docs/plans/2026-10-13-effective-inputs-and-tables.md +39 -0
  7. package/manual/docs/plans/2026-10-13-plugin-defaults.md +45 -0
  8. package/manual/docs/plans/2026-10-14-issue7-recovery.md +33 -0
  9. package/manual/docs/plans/2026-10-14-issue8-10-workflows.md +26 -0
  10. package/manual/docs/plans/2026-10-14-issue9-completion.md +47 -0
  11. package/manual/docs/plans/2026-10-14-managed-execution.md +58 -0
  12. package/manual/docs/plans/2026-10-14-plugin-discovery-history.md +41 -0
  13. package/manual/docs/plans/2026-10-14-structured-reports.md +77 -0
  14. package/manual/docs/plans/2026-10-14-unreleased-review.md +47 -0
  15. package/manual/docs/plugin-development.md +175 -11
  16. package/manual/docs/releases.md +49 -6
  17. package/manual/docs/superpowers/plans/2026-10-13-command-shortcuts.md +3 -2
  18. package/manual/docs/superpowers/plans/2026-10-13-global-plugins.md +56 -0
  19. package/manual/docs/superpowers/plans/2026-10-13-tui-readable-sessions.md +21 -0
  20. package/manual/docs/superpowers/reviews/2026-10-13-0.5.3-review.md +28 -0
  21. package/manual/docs/superpowers/reviews/2026-10-13-command-shortcuts-review.md +7 -0
  22. package/manual/docs/superpowers/reviews/2026-10-13-tui-sessions-review.md +57 -0
  23. package/manual/docs/superpowers/reviews/2026-10-14-0.6.0-release-review.md +19 -0
  24. package/manual/docs/superpowers/specs/2026-10-13-issue-4-workflow-menu.md +23 -0
  25. package/manual/docs/superpowers/specs/2026-10-13-issue-5-results-and-history.md +20 -0
  26. package/manual/docs/terminal-commands.md +8 -0
  27. package/manual/docs/verification.md +47 -0
  28. package/manual/packages/core/README.md +8 -0
  29. package/manual/packages/core/package.json +1 -1
  30. package/manual/packages/core/src/application.js +108 -53
  31. package/manual/packages/core/src/development-watch-worker.js +10 -1
  32. package/manual/packages/core/src/development.js +1 -1
  33. package/manual/packages/core/src/plugin-catalog.js +60 -0
  34. package/manual/packages/core/src/plugin-loading.js +24 -0
  35. package/manual/packages/core/src/version.js +1 -1
  36. package/manual/packages/fst-cli/README.md +8 -0
  37. package/manual/packages/fst-cli/bin/fst.js +7 -6
  38. package/manual/packages/fst-cli/package.json +1 -1
  39. package/manual/packages/fst-cli/src/development.js +6 -1
  40. package/manual/packages/fst-cli/src/terminal/command-menu.js +11 -5
  41. package/manual/packages/fst-cli/src/terminal/file-autocomplete.js +106 -0
  42. package/manual/packages/fst-cli/src/terminal/log-viewer.js +4 -3
  43. package/manual/packages/fst-cli/src/terminal/navigation.js +25 -1
  44. package/manual/packages/fst-cli/src/terminal/presentation.js +5 -3
  45. package/manual/packages/fst-cli/src/terminal/report-presentation.js +38 -0
  46. package/manual/packages/fst-cli/src/terminal/result-table.js +66 -0
  47. package/manual/packages/fst-cli/src/terminal/run-feed.js +104 -23
  48. package/manual/packages/fst-cli/src/terminal/run-presentation.js +91 -14
  49. package/manual/packages/fst-cli/src/terminal/run-viewer.js +34 -15
  50. package/manual/packages/fst-cli/src/terminal/schema.js +114 -4
  51. package/manual/packages/fst-cli/src/terminal/session-history.js +82 -0
  52. package/manual/packages/fst-cli/src/terminal/session.js +158 -54
  53. package/manual/packages/fst-cli/src/terminal/view.js +108 -73
  54. package/manual/packages/fst-cli/src/terminal/workflow-menu.js +17 -10
  55. package/manual/packages/fst-devtools/README.md +2 -0
  56. package/manual/packages/fst-devtools/package.json +2 -2
  57. package/manual/packages/fst-devtools/src/plugin-quality.js +4 -1
  58. package/manual/packages/fst-devtools/src/plugin-tools.js +2 -1
  59. package/manual/packages/fst-devtools/src/process-usage.js +62 -0
  60. package/manual/packages/fst-logs/README.md +23 -2
  61. package/manual/packages/fst-logs/package.json +2 -1
  62. package/manual/packages/fst-logs/src/file-identity.js +23 -0
  63. package/manual/packages/fst-logs/src/markdown-log.js +4 -3
  64. package/manual/packages/fst-logs/src/run-logs.js +3 -2
  65. package/manual/packages/fst-logs/src/session-history.js +180 -0
  66. package/manual/packages/fst-platform/README.md +9 -0
  67. package/manual/packages/fst-platform/package.json +4 -3
  68. package/manual/packages/fst-platform/src/managed-process.js +36 -0
  69. package/manual/packages/fst-platform/src/process.js +11 -3
  70. package/manual/packages/fst-platform/src/shell.js +46 -1
  71. package/manual/packages/fst-plugin/README.md +4 -0
  72. package/manual/packages/fst-plugin/package.json +1 -1
  73. package/manual/packages/fst-plugin/src/contracts.js +3 -0
  74. package/manual/packages/fst-plugin/src/host.js +54 -31
  75. package/manual/packages/fst-plugin/src/runtime.js +14 -8
  76. package/manual/packages/fst-workflow/package.json +1 -1
  77. package/manual/packages/fst-workflow/src/engine.js +1 -1
  78. package/manual/packages/fst-workspace/README.md +6 -0
  79. package/manual/packages/fst-workspace/package.json +2 -1
  80. package/manual/packages/fst-workspace/src/plugin-registry.js +58 -0
  81. package/manual/packages/fst-workspace/src/plugins.js +10 -5
  82. package/manual/packages/fst-workspace/src/workflows.js +32 -12
  83. package/manual/packages/pack/package.json +3 -3
  84. package/manual/packages/pack/runtime-cache.js +26 -0
  85. package/manual/packages/pack/runtime.js +6 -10
  86. package/manual/packages/sdk/README.md +10 -0
  87. package/manual/packages/sdk/inputs.js +53 -0
  88. package/manual/packages/sdk/package.json +2 -0
  89. package/manual/packages/sdk/reports.js +53 -0
  90. package/manual/plugins/commands/package.json +1 -1
  91. package/node_modules/@mytools/commands/package.json +1 -1
  92. package/node_modules/@mytools/core/README.md +8 -0
  93. package/node_modules/@mytools/core/package.json +1 -1
  94. package/node_modules/@mytools/core/src/application.js +108 -53
  95. package/node_modules/@mytools/core/src/development-watch-worker.js +10 -1
  96. package/node_modules/@mytools/core/src/development.js +1 -1
  97. package/node_modules/@mytools/core/src/plugin-catalog.js +60 -0
  98. package/node_modules/@mytools/core/src/plugin-loading.js +24 -0
  99. package/node_modules/@mytools/core/src/version.js +1 -1
  100. package/node_modules/@mytools/fst-cli/README.md +8 -0
  101. package/node_modules/@mytools/fst-cli/bin/fst.js +7 -6
  102. package/node_modules/@mytools/fst-cli/package.json +1 -1
  103. package/node_modules/@mytools/fst-cli/src/development.js +6 -1
  104. package/node_modules/@mytools/fst-cli/src/terminal/command-menu.js +11 -5
  105. package/node_modules/@mytools/fst-cli/src/terminal/file-autocomplete.js +106 -0
  106. package/node_modules/@mytools/fst-cli/src/terminal/log-viewer.js +4 -3
  107. package/node_modules/@mytools/fst-cli/src/terminal/navigation.js +25 -1
  108. package/node_modules/@mytools/fst-cli/src/terminal/presentation.js +5 -3
  109. package/node_modules/@mytools/fst-cli/src/terminal/report-presentation.js +38 -0
  110. package/node_modules/@mytools/fst-cli/src/terminal/result-table.js +66 -0
  111. package/node_modules/@mytools/fst-cli/src/terminal/run-feed.js +104 -23
  112. package/node_modules/@mytools/fst-cli/src/terminal/run-presentation.js +91 -14
  113. package/node_modules/@mytools/fst-cli/src/terminal/run-viewer.js +34 -15
  114. package/node_modules/@mytools/fst-cli/src/terminal/schema.js +114 -4
  115. package/node_modules/@mytools/fst-cli/src/terminal/session-history.js +82 -0
  116. package/node_modules/@mytools/fst-cli/src/terminal/session.js +158 -54
  117. package/node_modules/@mytools/fst-cli/src/terminal/view.js +108 -73
  118. package/node_modules/@mytools/fst-cli/src/terminal/workflow-menu.js +17 -10
  119. package/node_modules/@mytools/fst-devtools/README.md +2 -0
  120. package/node_modules/@mytools/fst-devtools/package.json +2 -2
  121. package/node_modules/@mytools/fst-devtools/src/plugin-quality.js +4 -1
  122. package/node_modules/@mytools/fst-devtools/src/plugin-tools.js +2 -1
  123. package/node_modules/@mytools/fst-devtools/src/process-usage.js +62 -0
  124. package/node_modules/@mytools/fst-logs/README.md +23 -2
  125. package/node_modules/@mytools/fst-logs/package.json +2 -1
  126. package/node_modules/@mytools/fst-logs/src/file-identity.js +23 -0
  127. package/node_modules/@mytools/fst-logs/src/markdown-log.js +4 -3
  128. package/node_modules/@mytools/fst-logs/src/run-logs.js +3 -2
  129. package/node_modules/@mytools/fst-logs/src/session-history.js +180 -0
  130. package/node_modules/@mytools/fst-platform/README.md +9 -0
  131. package/node_modules/@mytools/fst-platform/node_modules/undici/LICENSE +21 -0
  132. package/node_modules/{undici/docs/docs/index.md → @mytools/fst-platform/node_modules/undici/README.md} +85 -137
  133. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Agent.md +84 -0
  134. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
  135. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
  136. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
  137. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Client.md +288 -0
  138. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
  139. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Connector.md +115 -0
  140. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/ContentType.md +57 -0
  141. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Cookies.md +128 -0
  142. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Debug.md +62 -0
  143. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +317 -0
  144. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Dispatcher.md +1393 -0
  145. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
  146. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Errors.md +49 -0
  147. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/EventSource.md +45 -0
  148. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Fetch.md +60 -0
  149. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/GlobalInstallation.md +139 -0
  150. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/H2CClient.md +263 -0
  151. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
  152. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
  153. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
  154. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockClient.md +81 -0
  155. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
  156. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockPool.md +555 -0
  157. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Pool.md +84 -0
  158. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
  159. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/ProxyAgent.md +229 -0
  160. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RedirectHandler.md +93 -0
  161. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RetryAgent.md +50 -0
  162. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RetryHandler.md +118 -0
  163. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RoundRobinPool.md +145 -0
  164. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/SnapshotAgent.md +616 -0
  165. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +275 -0
  166. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Util.md +25 -0
  167. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/WebSocket.md +141 -0
  168. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
  169. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
  170. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/docs/docs/best-practices/crawling.md +1 -3
  171. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
  172. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
  173. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/docs/docs/best-practices/undici-vs-builtin-fetch.md +8 -10
  174. package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/writing-tests.md +63 -0
  175. package/node_modules/@mytools/fst-platform/node_modules/undici/index-fetch.js +65 -0
  176. package/node_modules/@mytools/fst-platform/node_modules/undici/index.d.ts +3 -0
  177. package/node_modules/@mytools/fst-platform/node_modules/undici/index.js +234 -0
  178. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/abort-signal.js +59 -0
  179. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-connect.js +110 -0
  180. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-pipeline.js +252 -0
  181. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-request.js +214 -0
  182. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-stream.js +209 -0
  183. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-upgrade.js +111 -0
  184. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/index.js +7 -0
  185. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/readable.js +580 -0
  186. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/cache/memory-cache-store.js +3 -3
  187. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/cache/sqlite-cache-store.js +1 -3
  188. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/connect.js +153 -0
  189. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/constants.js +143 -0
  190. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/diagnostics.js +227 -0
  191. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/errors.js +477 -0
  192. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/request.js +485 -0
  193. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/symbols.js +75 -0
  194. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/tree.js +160 -0
  195. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/util.js +992 -0
  196. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/agent.js +158 -0
  197. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/balanced-pool.js +221 -0
  198. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/client-h1.js +1746 -0
  199. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/client-h2.js +1060 -0
  200. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/client.js +668 -0
  201. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/dispatcher-base.js +184 -0
  202. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
  203. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
  204. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
  205. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/dispatcher/h2c-client.js +4 -4
  206. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
  207. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/pool.js +118 -0
  208. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/proxy-agent.js +319 -0
  209. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
  210. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/dispatcher/round-robin-pool.js +10 -32
  211. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/dispatcher/socks5-proxy-agent.js +63 -153
  212. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/global.js +59 -0
  213. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/handler/cache-handler.js +7 -49
  214. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/handler/cache-revalidation-handler.js +0 -10
  215. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/decorator-handler.js +67 -0
  216. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/handler/deduplication-handler.js +10 -29
  217. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/redirect-handler.js +238 -0
  218. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/retry-handler.js +504 -0
  219. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/unwrap-handler.js +106 -0
  220. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/wrap-handler.js +105 -0
  221. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/interceptor/cache.js +26 -79
  222. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/interceptor/decompress.js +3 -13
  223. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/interceptor/deduplicate.js +4 -5
  224. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/dns.js +571 -0
  225. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/dump.js +99 -0
  226. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/redirect.js +21 -0
  227. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/response-error.js +95 -0
  228. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/retry.js +19 -0
  229. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  230. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/constants.js +531 -0
  231. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
  232. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
  233. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/utils.js +12 -0
  234. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-agent.js +232 -0
  235. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/mock-call-history.js +1 -1
  236. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-client.js +68 -0
  237. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-errors.js +29 -0
  238. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
  239. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-pool.js +68 -0
  240. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-symbols.js +32 -0
  241. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-utils.js +486 -0
  242. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
  243. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/snapshot-agent.js +7 -25
  244. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/snapshot-recorder.js +3 -38
  245. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/cache.js +10 -92
  246. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/util/promise.js +28 -0
  247. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/runtime-features.js +34 -3
  248. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/util/timers.js +425 -0
  249. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cache/cache.js +864 -0
  250. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
  251. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cache/util.js +45 -0
  252. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/constants.js +12 -0
  253. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/index.js +199 -0
  254. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/parse.js +314 -0
  255. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/util.js +352 -0
  256. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/eventsource/eventsource-stream.js +494 -0
  257. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
  258. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/eventsource/util.js +29 -0
  259. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/LICENSE +21 -0
  260. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/body.js +509 -0
  261. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/constants.js +131 -0
  262. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/data-url.js +596 -0
  263. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/formdata-parser.js +586 -0
  264. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/formdata.js +259 -0
  265. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/global.js +40 -0
  266. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/headers.js +719 -0
  267. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/index.js +2413 -0
  268. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/request.js +1115 -0
  269. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/response.js +641 -0
  270. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/util.js +1522 -0
  271. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/infra/index.js +1 -16
  272. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/webidl/index.js +21 -7
  273. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/connection.js +339 -0
  274. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/constants.js +126 -0
  275. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/events.js +331 -0
  276. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/frame.js +133 -0
  277. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/permessage-deflate.js +105 -0
  278. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/receiver.js +507 -0
  279. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/sender.js +109 -0
  280. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/websocket/stream/websocketerror.js +10 -13
  281. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/websocket/stream/websocketstream.js +14 -29
  282. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/util.js +347 -0
  283. package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/websocket.js +758 -0
  284. package/node_modules/@mytools/fst-platform/node_modules/undici/package.json +152 -0
  285. package/node_modules/@mytools/fst-platform/node_modules/undici/scripts/strip-comments.js +10 -0
  286. package/node_modules/@mytools/fst-platform/node_modules/undici/types/README.md +6 -0
  287. package/node_modules/@mytools/fst-platform/node_modules/undici/types/agent.d.ts +32 -0
  288. package/node_modules/@mytools/fst-platform/node_modules/undici/types/api.d.ts +43 -0
  289. package/node_modules/@mytools/fst-platform/node_modules/undici/types/balanced-pool.d.ts +30 -0
  290. package/node_modules/@mytools/fst-platform/node_modules/undici/types/cache.d.ts +36 -0
  291. package/node_modules/@mytools/fst-platform/node_modules/undici/types/client.d.ts +139 -0
  292. package/node_modules/@mytools/fst-platform/node_modules/undici/types/connector.d.ts +36 -0
  293. package/node_modules/@mytools/fst-platform/node_modules/undici/types/content-type.d.ts +21 -0
  294. package/node_modules/@mytools/fst-platform/node_modules/undici/types/cookies.d.ts +30 -0
  295. package/node_modules/@mytools/fst-platform/node_modules/undici/types/diagnostics-channel.d.ts +74 -0
  296. package/node_modules/@mytools/fst-platform/node_modules/undici/types/dispatcher.d.ts +275 -0
  297. package/node_modules/@mytools/fst-platform/node_modules/undici/types/env-http-proxy-agent.d.ts +22 -0
  298. package/node_modules/@mytools/fst-platform/node_modules/undici/types/errors.d.ts +177 -0
  299. package/node_modules/@mytools/fst-platform/node_modules/undici/types/eventsource.d.ts +66 -0
  300. package/node_modules/@mytools/fst-platform/node_modules/undici/types/fetch.d.ts +231 -0
  301. package/node_modules/@mytools/fst-platform/node_modules/undici/types/formdata.d.ts +114 -0
  302. package/node_modules/@mytools/fst-platform/node_modules/undici/types/global-dispatcher.d.ts +9 -0
  303. package/node_modules/@mytools/fst-platform/node_modules/undici/types/global-origin.d.ts +7 -0
  304. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/h2c-client.d.ts +6 -6
  305. package/node_modules/@mytools/fst-platform/node_modules/undici/types/handlers.d.ts +14 -0
  306. package/node_modules/@mytools/fst-platform/node_modules/undici/types/header.d.ts +160 -0
  307. package/node_modules/@mytools/fst-platform/node_modules/undici/types/index.d.ts +91 -0
  308. package/node_modules/@mytools/fst-platform/node_modules/undici/types/interceptors.d.ts +82 -0
  309. package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-agent.d.ts +68 -0
  310. package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-client.d.ts +27 -0
  311. package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-errors.d.ts +12 -0
  312. package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-interceptor.d.ts +94 -0
  313. package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-pool.d.ts +27 -0
  314. package/node_modules/@mytools/fst-platform/node_modules/undici/types/patch.d.ts +29 -0
  315. package/node_modules/@mytools/fst-platform/node_modules/undici/types/pool-stats.d.ts +19 -0
  316. package/node_modules/@mytools/fst-platform/node_modules/undici/types/pool.d.ts +41 -0
  317. package/node_modules/@mytools/fst-platform/node_modules/undici/types/proxy-agent.d.ts +29 -0
  318. package/node_modules/@mytools/fst-platform/node_modules/undici/types/readable.d.ts +68 -0
  319. package/node_modules/@mytools/fst-platform/node_modules/undici/types/retry-agent.d.ts +8 -0
  320. package/node_modules/@mytools/fst-platform/node_modules/undici/types/retry-handler.d.ts +125 -0
  321. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/round-robin-pool.d.ts +2 -0
  322. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/snapshot-agent.d.ts +0 -4
  323. package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/socks5-proxy-agent.d.ts +2 -4
  324. package/node_modules/@mytools/fst-platform/node_modules/undici/types/util.d.ts +18 -0
  325. package/node_modules/@mytools/fst-platform/node_modules/undici/types/webidl.d.ts +347 -0
  326. package/node_modules/@mytools/fst-platform/node_modules/undici/types/websocket.d.ts +188 -0
  327. package/node_modules/@mytools/fst-platform/package.json +4 -3
  328. package/node_modules/@mytools/fst-platform/src/managed-process.js +36 -0
  329. package/node_modules/@mytools/fst-platform/src/process.js +11 -3
  330. package/node_modules/@mytools/fst-platform/src/shell.js +46 -1
  331. package/node_modules/@mytools/fst-plugin/README.md +4 -0
  332. package/node_modules/@mytools/fst-plugin/package.json +1 -1
  333. package/node_modules/@mytools/fst-plugin/src/contracts.js +3 -0
  334. package/node_modules/@mytools/fst-plugin/src/host.js +54 -31
  335. package/node_modules/@mytools/fst-plugin/src/runtime.js +14 -8
  336. package/node_modules/@mytools/fst-workflow/package.json +1 -1
  337. package/node_modules/@mytools/fst-workflow/src/engine.js +1 -1
  338. package/node_modules/@mytools/fst-workspace/README.md +6 -0
  339. package/node_modules/@mytools/fst-workspace/package.json +2 -1
  340. package/node_modules/@mytools/fst-workspace/src/plugin-registry.js +58 -0
  341. package/node_modules/@mytools/fst-workspace/src/plugins.js +10 -5
  342. package/node_modules/@mytools/fst-workspace/src/workflows.js +32 -12
  343. package/node_modules/@mytools/pack/package.json +3 -3
  344. package/node_modules/@mytools/pack/runtime-cache.js +26 -0
  345. package/node_modules/@mytools/pack/runtime.js +6 -10
  346. package/node_modules/@mytools/sdk/README.md +10 -0
  347. package/node_modules/@mytools/sdk/inputs.js +53 -0
  348. package/node_modules/@mytools/sdk/package.json +2 -0
  349. package/node_modules/@mytools/sdk/reports.js +53 -0
  350. package/node_modules/@mytools/web/public/THIRD_PARTY_NOTICES.txt +1197 -1207
  351. package/node_modules/@npmcli/agent/lib/agents.js +0 -10
  352. package/node_modules/@npmcli/agent/package.json +12 -11
  353. package/node_modules/@npmcli/arborist/README.md +2 -2
  354. package/node_modules/@npmcli/arborist/bin/index.js +2 -1
  355. package/node_modules/@npmcli/arborist/bin/shrinkwrap.js +7 -0
  356. package/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js +25 -159
  357. package/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js +49 -11
  358. package/node_modules/@npmcli/arborist/lib/arborist/load-actual.js +0 -67
  359. package/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js +37 -5
  360. package/node_modules/@npmcli/arborist/lib/arborist/rebuild.js +8 -15
  361. package/node_modules/@npmcli/arborist/lib/arborist/reify.js +42 -59
  362. package/node_modules/@npmcli/arborist/lib/consistent-resolve.js +1 -1
  363. package/node_modules/@npmcli/arborist/lib/diff.js +22 -17
  364. package/node_modules/@npmcli/arborist/lib/edge.js +2 -22
  365. package/node_modules/@npmcli/arborist/lib/index.js +0 -2
  366. package/node_modules/@npmcli/arborist/lib/isolated-classes.js +1 -4
  367. package/node_modules/@npmcli/arborist/lib/node.js +9 -13
  368. package/node_modules/@npmcli/arborist/lib/place-dep.js +0 -6
  369. package/node_modules/@npmcli/arborist/lib/printable.js +5 -0
  370. package/node_modules/@npmcli/arborist/lib/shrinkwrap.js +32 -55
  371. package/node_modules/@npmcli/arborist/package.json +26 -32
  372. package/node_modules/@npmcli/fs/lib/move-file.js +5 -5
  373. package/node_modules/@npmcli/fs/package.json +5 -5
  374. package/node_modules/@npmcli/git/package.json +12 -13
  375. package/node_modules/@npmcli/installed-package-contents/package.json +7 -7
  376. package/node_modules/@npmcli/map-workspaces/package.json +7 -7
  377. package/node_modules/@npmcli/metavuln-calculator/package.json +16 -10
  378. package/node_modules/@npmcli/name-from-folder/package.json +16 -13
  379. package/node_modules/@npmcli/node-gyp/package.json +5 -5
  380. package/node_modules/@npmcli/package-json/lib/index.js +1 -2
  381. package/node_modules/@npmcli/package-json/lib/normalize.js +22 -23
  382. package/node_modules/@npmcli/package-json/package.json +10 -11
  383. package/node_modules/@npmcli/promise-spawn/README.md +2 -1
  384. package/node_modules/@npmcli/promise-spawn/package.json +5 -5
  385. package/node_modules/@npmcli/redact/package.json +4 -4
  386. package/node_modules/@npmcli/run-script/lib/is-server-package.js +11 -0
  387. package/node_modules/@npmcli/run-script/lib/make-spawn-args.js +6 -5
  388. package/node_modules/@npmcli/run-script/lib/run-script-pkg.js +13 -4
  389. package/node_modules/@npmcli/run-script/lib/run-script.js +2 -1
  390. package/node_modules/@npmcli/run-script/package.json +11 -12
  391. package/node_modules/@sigstore/bundle/README.md +1 -1
  392. package/node_modules/@sigstore/bundle/dist/error.js +0 -1
  393. package/node_modules/@sigstore/bundle/package.json +2 -2
  394. package/node_modules/@sigstore/core/README.md +1 -1
  395. package/node_modules/@sigstore/core/dist/asn1/length.js +1 -12
  396. package/node_modules/@sigstore/core/dist/asn1/obj.js +7 -25
  397. package/node_modules/@sigstore/core/dist/asn1/parse.js +5 -24
  398. package/node_modules/@sigstore/core/package.json +2 -2
  399. package/node_modules/@sigstore/sign/README.md +1 -1
  400. package/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js +1 -1
  401. package/node_modules/@sigstore/sign/package.json +9 -9
  402. package/node_modules/@sigstore/tuf/README.md +1 -1
  403. package/node_modules/@sigstore/tuf/package.json +4 -4
  404. package/node_modules/@sigstore/tuf/seeds.json +1 -1
  405. package/node_modules/@sigstore/verify/README.md +1 -1
  406. package/node_modules/@sigstore/verify/dist/bundle/dsse.d.ts +0 -1
  407. package/node_modules/@sigstore/verify/dist/bundle/dsse.js +0 -6
  408. package/node_modules/@sigstore/verify/dist/bundle/message.d.ts +0 -1
  409. package/node_modules/@sigstore/verify/dist/bundle/message.js +0 -5
  410. package/node_modules/@sigstore/verify/dist/policy.d.ts +1 -1
  411. package/node_modules/@sigstore/verify/dist/policy.js +2 -0
  412. package/node_modules/@sigstore/verify/dist/shared.types.d.ts +1 -6
  413. package/node_modules/@sigstore/verify/dist/tlog/checkpoint.js +3 -17
  414. package/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js +4 -4
  415. package/node_modules/@sigstore/verify/dist/tlog/index.js +1 -13
  416. package/node_modules/@sigstore/verify/dist/tlog/merkle.js +1 -12
  417. package/node_modules/@sigstore/verify/dist/verifier.js +5 -13
  418. package/node_modules/@sigstore/verify/package.json +5 -5
  419. package/node_modules/@tufjs/models/package.json +3 -3
  420. package/node_modules/abbrev/package.json +8 -9
  421. package/node_modules/agent-base/dist/helpers.d.ts +5 -0
  422. package/node_modules/agent-base/dist/helpers.d.ts.map +1 -1
  423. package/node_modules/agent-base/dist/helpers.js +34 -5
  424. package/node_modules/agent-base/dist/helpers.js.map +1 -1
  425. package/node_modules/agent-base/dist/index.d.ts +5 -1
  426. package/node_modules/agent-base/dist/index.d.ts.map +1 -1
  427. package/node_modules/agent-base/dist/index.js +40 -8
  428. package/node_modules/agent-base/dist/index.js.map +1 -1
  429. package/node_modules/agent-base/package.json +12 -12
  430. package/node_modules/bin-links/README.md +4 -5
  431. package/node_modules/bin-links/lib/fix-bin.js +1 -3
  432. package/node_modules/bin-links/lib/index.js +16 -8
  433. package/node_modules/bin-links/lib/link-mans.js +53 -0
  434. package/node_modules/bin-links/package.json +12 -11
  435. package/node_modules/cacache/lib/content/write.js +0 -2
  436. package/node_modules/cacache/lib/entry-index.js +0 -3
  437. package/node_modules/cacache/lib/rm.js +0 -1
  438. package/node_modules/cacache/lib/util/tmp.js +1 -5
  439. package/node_modules/cacache/lib/verify.js +2 -2
  440. package/node_modules/cacache/package.json +7 -7
  441. package/node_modules/cmd-shim/lib/index.js +32 -67
  442. package/node_modules/cmd-shim/package.json +5 -5
  443. package/node_modules/hosted-git-info/README.md +1 -1
  444. package/node_modules/hosted-git-info/lib/parse-url.js +3 -1
  445. package/node_modules/hosted-git-info/package.json +4 -4
  446. package/node_modules/http-proxy-agent/dist/index.d.ts +5 -8
  447. package/node_modules/http-proxy-agent/dist/index.d.ts.map +1 -1
  448. package/node_modules/http-proxy-agent/dist/index.js +42 -26
  449. package/node_modules/http-proxy-agent/dist/index.js.map +1 -1
  450. package/node_modules/http-proxy-agent/package.json +14 -15
  451. package/node_modules/https-proxy-agent/dist/index.d.ts +5 -9
  452. package/node_modules/https-proxy-agent/dist/index.d.ts.map +1 -1
  453. package/node_modules/https-proxy-agent/dist/index.js +44 -98
  454. package/node_modules/https-proxy-agent/dist/index.js.map +1 -1
  455. package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +3 -0
  456. package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts.map +1 -1
  457. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +10 -3
  458. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -1
  459. package/node_modules/https-proxy-agent/package.json +15 -16
  460. package/node_modules/ignore-walk/package.json +4 -4
  461. package/node_modules/ini/package.json +5 -5
  462. package/node_modules/ip-address/README.md +70 -70
  463. package/node_modules/ip-address/dist/ipv6.js +7 -4
  464. package/node_modules/ip-address/dist/ipv6.js.map +1 -1
  465. package/node_modules/ip-address/dist/v6/constants.d.ts +3 -0
  466. package/node_modules/ip-address/dist/v6/constants.js +3 -0
  467. package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  468. package/node_modules/ip-address/package.json +2 -1
  469. package/node_modules/json-parse-even-better-errors/lib/index.js +1 -3
  470. package/node_modules/json-parse-even-better-errors/package.json +17 -13
  471. package/node_modules/make-fetch-happen/package.json +11 -11
  472. package/node_modules/minipass-fetch/package.json +4 -4
  473. package/node_modules/node-gyp/.release-please-manifest.json +1 -1
  474. package/node_modules/node-gyp/CHANGELOG.md +0 -102
  475. package/node_modules/node-gyp/README.md +2 -3
  476. package/node_modules/node-gyp/eslint.config.js +1 -4
  477. package/node_modules/node-gyp/gyp/.release-please-manifest.json +1 -1
  478. package/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +19 -14
  479. package/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +2 -7
  480. package/node_modules/node-gyp/gyp/pyproject.toml +1 -1
  481. package/node_modules/node-gyp/lib/build.js +6 -18
  482. package/node_modules/node-gyp/lib/create-config-gypi.js +0 -5
  483. package/node_modules/node-gyp/lib/node-gyp.js +2 -9
  484. package/node_modules/node-gyp/lib/rebuild.js +3 -3
  485. package/node_modules/node-gyp/package.json +9 -11
  486. package/node_modules/nopt/README.md +4 -2
  487. package/node_modules/nopt/lib/debug.js +5 -0
  488. package/node_modules/nopt/lib/nopt-lib.js +43 -7
  489. package/node_modules/nopt/lib/nopt.js +4 -2
  490. package/node_modules/nopt/lib/type-defs.js +13 -8
  491. package/node_modules/nopt/package.json +17 -15
  492. package/node_modules/npm-bundled/package.json +6 -6
  493. package/node_modules/npm-install-checks/package.json +5 -5
  494. package/node_modules/npm-normalize-package-bin/package.json +16 -13
  495. package/node_modules/npm-package-arg/package.json +7 -7
  496. package/node_modules/npm-packlist/README.md +30 -45
  497. package/node_modules/npm-packlist/lib/index.js +47 -115
  498. package/node_modules/npm-packlist/package.json +8 -10
  499. package/node_modules/npm-pick-manifest/package.json +19 -15
  500. package/node_modules/npm-registry-fetch/lib/errors.js +3 -8
  501. package/node_modules/npm-registry-fetch/package.json +12 -12
  502. package/node_modules/pacote/lib/dir.js +5 -60
  503. package/node_modules/pacote/lib/fetcher.js +0 -4
  504. package/node_modules/pacote/lib/git.js +3 -11
  505. package/node_modules/pacote/lib/util/add-git-sha.js +1 -1
  506. package/node_modules/pacote/package.json +18 -19
  507. package/node_modules/parse-conflict-json/package.json +6 -6
  508. package/node_modules/proc-log/package.json +4 -4
  509. package/node_modules/read-cmd-shim/lib/index.js +1 -1
  510. package/node_modules/read-cmd-shim/package.json +18 -14
  511. package/node_modules/sigstore/README.md +1 -1
  512. package/node_modules/sigstore/package.json +10 -10
  513. package/node_modules/socks-proxy-agent/dist/index.d.ts +3 -1
  514. package/node_modules/socks-proxy-agent/dist/index.d.ts.map +1 -1
  515. package/node_modules/socks-proxy-agent/dist/index.js +43 -17
  516. package/node_modules/socks-proxy-agent/dist/index.js.map +1 -1
  517. package/node_modules/socks-proxy-agent/package.json +15 -15
  518. package/node_modules/ssri/package.json +4 -4
  519. package/node_modules/tuf-js/dist/config.d.ts +2 -2
  520. package/node_modules/tuf-js/dist/fetcher.d.ts +4 -4
  521. package/node_modules/tuf-js/dist/fetcher.js +16 -55
  522. package/node_modules/tuf-js/dist/updater.js +2 -2
  523. package/node_modules/tuf-js/package.json +8 -8
  524. package/node_modules/undici/README.md +72 -405
  525. package/node_modules/undici/docs/docs/api/Agent.md +41 -252
  526. package/node_modules/undici/docs/docs/api/BalancedPool.md +48 -246
  527. package/node_modules/undici/docs/docs/api/CacheStorage.md +13 -171
  528. package/node_modules/undici/docs/docs/api/Client.md +139 -395
  529. package/node_modules/undici/docs/docs/api/Connector.md +35 -118
  530. package/node_modules/undici/docs/docs/api/ContentType.md +25 -65
  531. package/node_modules/undici/docs/docs/api/Cookies.md +47 -125
  532. package/node_modules/undici/docs/docs/api/Debug.md +31 -47
  533. package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +97 -409
  534. package/node_modules/undici/docs/docs/api/DispatchInterceptor.md +60 -0
  535. package/node_modules/undici/docs/docs/api/Dispatcher.md +1011 -500
  536. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +96 -105
  537. package/node_modules/undici/docs/docs/api/Errors.md +28 -528
  538. package/node_modules/undici/docs/docs/api/EventSource.md +13 -326
  539. package/node_modules/undici/docs/docs/api/Fetch.md +24 -693
  540. package/node_modules/undici/docs/docs/api/MockAgent.md +264 -346
  541. package/node_modules/undici/docs/docs/api/MockClient.md +31 -153
  542. package/node_modules/undici/docs/docs/api/MockErrors.md +5 -56
  543. package/node_modules/undici/docs/docs/api/MockPool.md +253 -324
  544. package/node_modules/undici/docs/docs/api/Pool.md +41 -235
  545. package/node_modules/undici/docs/docs/api/PoolStats.md +13 -119
  546. package/node_modules/undici/docs/docs/api/ProxyAgent.md +81 -198
  547. package/node_modules/undici/docs/docs/api/RedirectHandler.md +58 -238
  548. package/node_modules/undici/docs/docs/api/RetryAgent.md +28 -119
  549. package/node_modules/undici/docs/docs/api/RetryHandler.md +78 -161
  550. package/node_modules/undici/docs/docs/api/Util.md +11 -68
  551. package/node_modules/undici/docs/docs/api/WebSocket.md +24 -509
  552. package/node_modules/undici/docs/docs/api/api-lifecycle.md +33 -101
  553. package/node_modules/undici/docs/docs/best-practices/client-certificate.md +0 -2
  554. package/node_modules/undici/docs/docs/best-practices/mocking-request.md +2 -58
  555. package/node_modules/undici/docs/docs/best-practices/proxy.md +1 -3
  556. package/node_modules/undici/docs/docs/best-practices/writing-tests.md +0 -45
  557. package/node_modules/undici/index-fetch.js +4 -34
  558. package/node_modules/undici/index.d.ts +1 -1
  559. package/node_modules/undici/index.js +20 -87
  560. package/node_modules/undici/lib/api/abort-signal.js +0 -2
  561. package/node_modules/undici/lib/api/api-connect.js +11 -15
  562. package/node_modules/undici/lib/api/api-pipeline.js +19 -33
  563. package/node_modules/undici/lib/api/api-request.js +59 -89
  564. package/node_modules/undici/lib/api/api-stream.js +64 -114
  565. package/node_modules/undici/lib/api/api-upgrade.js +13 -26
  566. package/node_modules/undici/lib/api/readable.js +87 -317
  567. package/node_modules/undici/lib/api/util.js +93 -0
  568. package/node_modules/undici/lib/core/connect.js +125 -77
  569. package/node_modules/undici/lib/core/constants.js +9 -11
  570. package/node_modules/undici/lib/core/diagnostics.js +129 -154
  571. package/node_modules/undici/lib/core/errors.js +50 -122
  572. package/node_modules/undici/lib/core/request.js +87 -172
  573. package/node_modules/undici/lib/core/symbols.js +2 -14
  574. package/node_modules/undici/lib/core/tree.js +2 -10
  575. package/node_modules/undici/lib/core/util.js +190 -481
  576. package/node_modules/undici/lib/dispatcher/agent.js +35 -83
  577. package/node_modules/undici/lib/dispatcher/balanced-pool.js +38 -46
  578. package/node_modules/undici/lib/dispatcher/client-h1.js +199 -492
  579. package/node_modules/undici/lib/dispatcher/client-h2.js +380 -1409
  580. package/node_modules/undici/lib/dispatcher/client.js +130 -253
  581. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +52 -50
  582. package/node_modules/undici/lib/dispatcher/dispatcher.js +24 -17
  583. package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +45 -75
  584. package/node_modules/undici/lib/dispatcher/fixed-queue.js +50 -68
  585. package/node_modules/undici/lib/dispatcher/pool-base.js +54 -153
  586. package/node_modules/undici/lib/dispatcher/pool-stats.js +34 -0
  587. package/node_modules/undici/lib/dispatcher/pool.js +16 -135
  588. package/node_modules/undici/lib/dispatcher/proxy-agent.js +41 -175
  589. package/node_modules/undici/lib/dispatcher/retry-agent.js +0 -3
  590. package/node_modules/undici/lib/global.js +9 -59
  591. package/node_modules/undici/lib/handler/decorator-handler.js +15 -43
  592. package/node_modules/undici/lib/handler/redirect-handler.js +116 -127
  593. package/node_modules/undici/lib/handler/retry-handler.js +182 -398
  594. package/node_modules/undici/lib/interceptor/dns.js +47 -254
  595. package/node_modules/undici/lib/interceptor/dump.js +56 -32
  596. package/node_modules/undici/lib/interceptor/redirect-interceptor.js +21 -0
  597. package/node_modules/undici/lib/interceptor/redirect.js +14 -11
  598. package/node_modules/undici/lib/interceptor/response-error.js +22 -31
  599. package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  600. package/node_modules/undici/lib/llhttp/constants.js +193 -446
  601. package/node_modules/undici/lib/llhttp/llhttp-wasm.js +1 -11
  602. package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +1 -11
  603. package/node_modules/undici/lib/llhttp/utils.js +12 -9
  604. package/node_modules/undici/lib/mock/mock-agent.js +22 -106
  605. package/node_modules/undici/lib/mock/mock-client.js +4 -13
  606. package/node_modules/undici/lib/mock/mock-errors.js +2 -3
  607. package/node_modules/undici/lib/mock/mock-interceptor.js +13 -33
  608. package/node_modules/undici/lib/mock/mock-pool.js +4 -13
  609. package/node_modules/undici/lib/mock/mock-symbols.js +1 -10
  610. package/node_modules/undici/lib/mock/mock-utils.js +51 -404
  611. package/node_modules/undici/lib/mock/pluralizer.js +29 -0
  612. package/node_modules/undici/lib/util/timers.js +9 -11
  613. package/node_modules/undici/lib/web/cache/cache.js +51 -63
  614. package/node_modules/undici/lib/web/cache/cachestorage.js +7 -13
  615. package/node_modules/undici/lib/web/cache/symbols.js +5 -0
  616. package/node_modules/undici/lib/web/cookies/index.js +18 -45
  617. package/node_modules/undici/lib/web/cookies/parse.js +149 -157
  618. package/node_modules/undici/lib/web/cookies/util.js +2 -4
  619. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +9 -37
  620. package/node_modules/undici/lib/web/eventsource/eventsource.js +64 -108
  621. package/node_modules/undici/lib/web/eventsource/util.js +5 -28
  622. package/node_modules/undici/lib/web/fetch/body.js +148 -173
  623. package/node_modules/undici/lib/web/fetch/constants.js +6 -13
  624. package/node_modules/undici/lib/web/fetch/data-url.js +167 -19
  625. package/node_modules/undici/lib/web/fetch/dispatcher-weakref.js +46 -0
  626. package/node_modules/undici/lib/web/fetch/file.js +126 -0
  627. package/node_modules/undici/lib/web/fetch/formdata-parser.js +117 -229
  628. package/node_modules/undici/lib/web/fetch/formdata.js +65 -85
  629. package/node_modules/undici/lib/web/fetch/headers.js +108 -143
  630. package/node_modules/undici/lib/web/fetch/index.js +446 -627
  631. package/node_modules/undici/lib/web/fetch/request.js +115 -217
  632. package/node_modules/undici/lib/web/fetch/response.js +82 -110
  633. package/node_modules/undici/lib/web/fetch/symbols.js +9 -0
  634. package/node_modules/undici/lib/web/fetch/util.js +393 -291
  635. package/node_modules/undici/lib/web/fetch/webidl.js +695 -0
  636. package/node_modules/undici/lib/web/fileapi/encoding.js +290 -0
  637. package/node_modules/undici/lib/web/fileapi/filereader.js +344 -0
  638. package/node_modules/undici/lib/web/fileapi/progressevent.js +78 -0
  639. package/node_modules/undici/lib/web/fileapi/symbols.js +10 -0
  640. package/node_modules/undici/lib/web/fileapi/util.js +391 -0
  641. package/node_modules/undici/lib/web/websocket/connection.js +160 -139
  642. package/node_modules/undici/lib/web/websocket/constants.js +10 -70
  643. package/node_modules/undici/lib/web/websocket/events.js +30 -49
  644. package/node_modules/undici/lib/web/websocket/frame.js +20 -51
  645. package/node_modules/undici/lib/web/websocket/receiver.js +87 -83
  646. package/node_modules/undici/lib/web/websocket/sender.js +13 -18
  647. package/node_modules/undici/lib/web/websocket/symbols.js +12 -0
  648. package/node_modules/undici/lib/web/websocket/util.js +90 -115
  649. package/node_modules/undici/lib/web/websocket/websocket.js +171 -359
  650. package/node_modules/undici/package.json +57 -49
  651. package/node_modules/undici/scripts/strip-comments.js +1 -3
  652. package/node_modules/undici/types/agent.d.ts +13 -12
  653. package/node_modules/undici/types/api.d.ts +26 -26
  654. package/node_modules/undici/types/balanced-pool.d.ts +12 -13
  655. package/node_modules/undici/types/client.d.ts +39 -98
  656. package/node_modules/undici/types/connector.d.ts +2 -5
  657. package/node_modules/undici/types/cookies.d.ts +1 -3
  658. package/node_modules/undici/types/diagnostics-channel.d.ts +11 -20
  659. package/node_modules/undici/types/dispatcher.d.ts +139 -136
  660. package/node_modules/undici/types/env-http-proxy-agent.d.ts +3 -4
  661. package/node_modules/undici/types/errors.d.ts +54 -86
  662. package/node_modules/undici/types/eventsource.d.ts +4 -9
  663. package/node_modules/undici/types/fetch.d.ts +25 -51
  664. package/node_modules/undici/types/file.d.ts +39 -0
  665. package/node_modules/undici/types/filereader.d.ts +54 -0
  666. package/node_modules/undici/types/formdata.d.ts +7 -7
  667. package/node_modules/undici/types/global-dispatcher.d.ts +4 -4
  668. package/node_modules/undici/types/global-origin.d.ts +5 -5
  669. package/node_modules/undici/types/handlers.d.ts +9 -10
  670. package/node_modules/undici/types/header.d.ts +1 -162
  671. package/node_modules/undici/types/index.d.ts +47 -69
  672. package/node_modules/undici/types/interceptors.d.ts +12 -62
  673. package/node_modules/undici/types/mock-agent.d.ts +27 -46
  674. package/node_modules/undici/types/mock-client.d.ts +4 -6
  675. package/node_modules/undici/types/mock-errors.d.ts +3 -3
  676. package/node_modules/undici/types/mock-interceptor.d.ts +21 -26
  677. package/node_modules/undici/types/mock-pool.d.ts +4 -6
  678. package/node_modules/undici/types/patch.d.ts +4 -0
  679. package/node_modules/undici/types/pool-stats.d.ts +8 -8
  680. package/node_modules/undici/types/pool.d.ts +14 -14
  681. package/node_modules/undici/types/proxy-agent.d.ts +6 -13
  682. package/node_modules/undici/types/readable.d.ts +16 -19
  683. package/node_modules/undici/types/retry-agent.d.ts +1 -1
  684. package/node_modules/undici/types/retry-handler.d.ts +9 -18
  685. package/node_modules/undici/types/util.d.ts +3 -3
  686. package/node_modules/undici/types/webidl.d.ts +32 -156
  687. package/node_modules/undici/types/websocket.d.ts +10 -48
  688. package/node_modules/validate-npm-package-name/package.json +4 -4
  689. package/node_modules/which/package.json +4 -4
  690. package/node_modules/write-file-atomic/package.json +4 -4
  691. package/package.json +56 -60
  692. package/node_modules/@npmcli/arborist/lib/npm-extension.js +0 -237
  693. package/node_modules/@npmcli/arborist/lib/package-extensions.js +0 -236
  694. package/node_modules/@npmcli/arborist/lib/patch.js +0 -111
  695. package/node_modules/@npmcli/arborist/lib/patched-dependencies.js +0 -168
  696. package/node_modules/cacache/lib/util/cache-dir.js +0 -29
  697. package/node_modules/diff/CONTRIBUTING.md +0 -28
  698. package/node_modules/diff/LICENSE +0 -29
  699. package/node_modules/diff/README.md +0 -388
  700. package/node_modules/diff/dist/diff.js +0 -1782
  701. package/node_modules/diff/dist/diff.min.js +0 -1
  702. package/node_modules/diff/eslint.config.mjs +0 -182
  703. package/node_modules/diff/libcjs/convert/dmp.d.ts +0 -8
  704. package/node_modules/diff/libcjs/convert/dmp.d.ts.map +0 -1
  705. package/node_modules/diff/libcjs/convert/dmp.js +0 -24
  706. package/node_modules/diff/libcjs/convert/xml.d.ts +0 -6
  707. package/node_modules/diff/libcjs/convert/xml.d.ts.map +0 -1
  708. package/node_modules/diff/libcjs/convert/xml.js +0 -34
  709. package/node_modules/diff/libcjs/diff/array.d.ts +0 -19
  710. package/node_modules/diff/libcjs/diff/array.d.ts.map +0 -1
  711. package/node_modules/diff/libcjs/diff/array.js +0 -40
  712. package/node_modules/diff/libcjs/diff/base.d.ts +0 -20
  713. package/node_modules/diff/libcjs/diff/base.d.ts.map +0 -1
  714. package/node_modules/diff/libcjs/diff/base.js +0 -265
  715. package/node_modules/diff/libcjs/diff/character.d.ts +0 -19
  716. package/node_modules/diff/libcjs/diff/character.d.ts.map +0 -1
  717. package/node_modules/diff/libcjs/diff/character.js +0 -31
  718. package/node_modules/diff/libcjs/diff/css.d.ts +0 -18
  719. package/node_modules/diff/libcjs/diff/css.d.ts.map +0 -1
  720. package/node_modules/diff/libcjs/diff/css.js +0 -34
  721. package/node_modules/diff/libcjs/diff/json.d.ts +0 -24
  722. package/node_modules/diff/libcjs/diff/json.d.ts.map +0 -1
  723. package/node_modules/diff/libcjs/diff/json.js +0 -105
  724. package/node_modules/diff/libcjs/diff/line.d.ts +0 -24
  725. package/node_modules/diff/libcjs/diff/line.d.ts.map +0 -1
  726. package/node_modules/diff/libcjs/diff/line.js +0 -89
  727. package/node_modules/diff/libcjs/diff/sentence.d.ts +0 -21
  728. package/node_modules/diff/libcjs/diff/sentence.d.ts.map +0 -1
  729. package/node_modules/diff/libcjs/diff/sentence.js +0 -67
  730. package/node_modules/diff/libcjs/diff/word.d.ts +0 -35
  731. package/node_modules/diff/libcjs/diff/word.d.ts.map +0 -1
  732. package/node_modules/diff/libcjs/diff/word.js +0 -312
  733. package/node_modules/diff/libcjs/index.d.ts +0 -20
  734. package/node_modules/diff/libcjs/index.d.ts.map +0 -1
  735. package/node_modules/diff/libcjs/index.js +0 -64
  736. package/node_modules/diff/libcjs/package.json +0 -1
  737. package/node_modules/diff/libcjs/patch/apply.d.ts +0 -62
  738. package/node_modules/diff/libcjs/patch/apply.d.ts.map +0 -1
  739. package/node_modules/diff/libcjs/patch/apply.js +0 -267
  740. package/node_modules/diff/libcjs/patch/create.d.ts +0 -122
  741. package/node_modules/diff/libcjs/patch/create.d.ts.map +0 -1
  742. package/node_modules/diff/libcjs/patch/create.js +0 -251
  743. package/node_modules/diff/libcjs/patch/line-endings.d.ts +0 -17
  744. package/node_modules/diff/libcjs/patch/line-endings.d.ts.map +0 -1
  745. package/node_modules/diff/libcjs/patch/line-endings.js +0 -61
  746. package/node_modules/diff/libcjs/patch/parse.d.ts +0 -8
  747. package/node_modules/diff/libcjs/patch/parse.d.ts.map +0 -1
  748. package/node_modules/diff/libcjs/patch/parse.js +0 -150
  749. package/node_modules/diff/libcjs/patch/reverse.d.ts +0 -9
  750. package/node_modules/diff/libcjs/patch/reverse.d.ts.map +0 -1
  751. package/node_modules/diff/libcjs/patch/reverse.js +0 -37
  752. package/node_modules/diff/libcjs/types.d.ts +0 -213
  753. package/node_modules/diff/libcjs/types.d.ts.map +0 -1
  754. package/node_modules/diff/libcjs/types.js +0 -2
  755. package/node_modules/diff/libcjs/util/array.d.ts +0 -3
  756. package/node_modules/diff/libcjs/util/array.d.ts.map +0 -1
  757. package/node_modules/diff/libcjs/util/array.js +0 -21
  758. package/node_modules/diff/libcjs/util/distance-iterator.d.ts +0 -2
  759. package/node_modules/diff/libcjs/util/distance-iterator.d.ts.map +0 -1
  760. package/node_modules/diff/libcjs/util/distance-iterator.js +0 -40
  761. package/node_modules/diff/libcjs/util/params.d.ts +0 -4
  762. package/node_modules/diff/libcjs/util/params.d.ts.map +0 -1
  763. package/node_modules/diff/libcjs/util/params.js +0 -17
  764. package/node_modules/diff/libcjs/util/string.d.ts +0 -30
  765. package/node_modules/diff/libcjs/util/string.d.ts.map +0 -1
  766. package/node_modules/diff/libcjs/util/string.js +0 -200
  767. package/node_modules/diff/libesm/convert/dmp.d.ts +0 -8
  768. package/node_modules/diff/libesm/convert/dmp.d.ts.map +0 -1
  769. package/node_modules/diff/libesm/convert/dmp.js +0 -21
  770. package/node_modules/diff/libesm/convert/xml.d.ts +0 -6
  771. package/node_modules/diff/libesm/convert/xml.d.ts.map +0 -1
  772. package/node_modules/diff/libesm/convert/xml.js +0 -31
  773. package/node_modules/diff/libesm/diff/array.d.ts +0 -19
  774. package/node_modules/diff/libesm/diff/array.d.ts.map +0 -1
  775. package/node_modules/diff/libesm/diff/array.js +0 -16
  776. package/node_modules/diff/libesm/diff/base.d.ts +0 -20
  777. package/node_modules/diff/libesm/diff/base.d.ts.map +0 -1
  778. package/node_modules/diff/libesm/diff/base.js +0 -253
  779. package/node_modules/diff/libesm/diff/character.d.ts +0 -19
  780. package/node_modules/diff/libesm/diff/character.d.ts.map +0 -1
  781. package/node_modules/diff/libesm/diff/character.js +0 -7
  782. package/node_modules/diff/libesm/diff/css.d.ts +0 -18
  783. package/node_modules/diff/libesm/diff/css.d.ts.map +0 -1
  784. package/node_modules/diff/libesm/diff/css.js +0 -10
  785. package/node_modules/diff/libesm/diff/json.d.ts +0 -24
  786. package/node_modules/diff/libesm/diff/json.d.ts.map +0 -1
  787. package/node_modules/diff/libesm/diff/json.js +0 -78
  788. package/node_modules/diff/libesm/diff/line.d.ts +0 -24
  789. package/node_modules/diff/libesm/diff/line.d.ts.map +0 -1
  790. package/node_modules/diff/libesm/diff/line.js +0 -65
  791. package/node_modules/diff/libesm/diff/sentence.d.ts +0 -21
  792. package/node_modules/diff/libesm/diff/sentence.d.ts.map +0 -1
  793. package/node_modules/diff/libesm/diff/sentence.js +0 -43
  794. package/node_modules/diff/libesm/diff/word.d.ts +0 -35
  795. package/node_modules/diff/libesm/diff/word.d.ts.map +0 -1
  796. package/node_modules/diff/libesm/diff/word.js +0 -281
  797. package/node_modules/diff/libesm/index.d.ts +0 -20
  798. package/node_modules/diff/libesm/index.d.ts.map +0 -1
  799. package/node_modules/diff/libesm/index.js +0 -30
  800. package/node_modules/diff/libesm/package.json +0 -1
  801. package/node_modules/diff/libesm/patch/apply.d.ts +0 -62
  802. package/node_modules/diff/libesm/patch/apply.d.ts.map +0 -1
  803. package/node_modules/diff/libesm/patch/apply.js +0 -257
  804. package/node_modules/diff/libesm/patch/create.d.ts +0 -122
  805. package/node_modules/diff/libesm/patch/create.d.ts.map +0 -1
  806. package/node_modules/diff/libesm/patch/create.js +0 -228
  807. package/node_modules/diff/libesm/patch/line-endings.d.ts +0 -17
  808. package/node_modules/diff/libesm/patch/line-endings.d.ts.map +0 -1
  809. package/node_modules/diff/libesm/patch/line-endings.js +0 -44
  810. package/node_modules/diff/libesm/patch/parse.d.ts +0 -8
  811. package/node_modules/diff/libesm/patch/parse.d.ts.map +0 -1
  812. package/node_modules/diff/libesm/patch/parse.js +0 -147
  813. package/node_modules/diff/libesm/patch/reverse.d.ts +0 -9
  814. package/node_modules/diff/libesm/patch/reverse.d.ts.map +0 -1
  815. package/node_modules/diff/libesm/patch/reverse.js +0 -23
  816. package/node_modules/diff/libesm/types.d.ts +0 -213
  817. package/node_modules/diff/libesm/types.d.ts.map +0 -1
  818. package/node_modules/diff/libesm/types.js +0 -1
  819. package/node_modules/diff/libesm/util/array.d.ts +0 -3
  820. package/node_modules/diff/libesm/util/array.d.ts.map +0 -1
  821. package/node_modules/diff/libesm/util/array.js +0 -17
  822. package/node_modules/diff/libesm/util/distance-iterator.d.ts +0 -2
  823. package/node_modules/diff/libesm/util/distance-iterator.d.ts.map +0 -1
  824. package/node_modules/diff/libesm/util/distance-iterator.js +0 -37
  825. package/node_modules/diff/libesm/util/params.d.ts +0 -4
  826. package/node_modules/diff/libesm/util/params.d.ts.map +0 -1
  827. package/node_modules/diff/libesm/util/params.js +0 -14
  828. package/node_modules/diff/libesm/util/string.d.ts +0 -30
  829. package/node_modules/diff/libesm/util/string.d.ts.map +0 -1
  830. package/node_modules/diff/libesm/util/string.js +0 -184
  831. package/node_modules/diff/package.json +0 -130
  832. package/node_modules/diff/release-notes.md +0 -432
  833. package/node_modules/node-gyp/commitlint.config.mjs +0 -3
  834. package/node_modules/node-gyp/gyp/commitlint.config.js +0 -6
  835. package/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake_test.py +0 -105
  836. package/node_modules/node-gyp/zizmor.yml +0 -5
  837. package/node_modules/proxy-agent-negotiate/dist/index.d.ts +0 -14
  838. package/node_modules/proxy-agent-negotiate/dist/index.d.ts.map +0 -1
  839. package/node_modules/proxy-agent-negotiate/dist/index.js +0 -35
  840. package/node_modules/proxy-agent-negotiate/dist/index.js.map +0 -1
  841. package/node_modules/proxy-agent-negotiate/package.json +0 -47
  842. package/node_modules/undici/docs/docs/api/CacheStore.md +0 -360
  843. package/node_modules/undici/docs/docs/api/ClientStats.md +0 -93
  844. package/node_modules/undici/docs/docs/api/GlobalInstallation.md +0 -121
  845. package/node_modules/undici/docs/docs/api/H2CClient.md +0 -385
  846. package/node_modules/undici/docs/docs/api/Interceptors.md +0 -419
  847. package/node_modules/undici/docs/docs/api/MockCallHistory.md +0 -371
  848. package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +0 -206
  849. package/node_modules/undici/docs/docs/api/RoundRobinPool.md +0 -239
  850. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +0 -361
  851. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +0 -256
  852. package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +0 -233
  853. package/node_modules/undici/docs/docs/getting-started.md +0 -281
  854. package/node_modules/undici/docs/docs/site.json +0 -125
  855. package/node_modules/undici/docs/docs/type-map.json +0 -79
  856. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +0 -110
  857. package/node_modules/undici/types/dispatcher1-wrapper.d.ts +0 -7
  858. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/core/socks5-client.js +0 -0
  859. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/core/socks5-utils.js +0 -0
  860. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/encoding/index.js +0 -0
  861. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/llhttp/constants.d.ts +0 -0
  862. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/llhttp/utils.d.ts +0 -0
  863. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/snapshot-utils.js +0 -0
  864. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/date.js +0 -0
  865. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/stats.js +0 -0
  866. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/subresource-integrity/Readme.md +0 -0
  867. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/subresource-integrity/subresource-integrity.js +0 -0
  868. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/cache-interceptor.d.ts +0 -0
  869. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/client-stats.d.ts +0 -0
  870. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/mock-call-history.d.ts +0 -0
  871. /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/utility.d.ts +0 -0
@@ -1,18 +1,14 @@
1
1
  'use strict'
2
2
 
3
3
  const assert = require('node:assert')
4
+ const { errorMonitor } = require('node:events')
4
5
  const { pipeline } = require('node:stream')
5
6
  const util = require('../core/util.js')
6
7
  const {
7
8
  RequestContentLengthMismatchError,
8
- ResponseContentLengthMismatchError,
9
9
  RequestAbortedError,
10
10
  SocketError,
11
- InformationalError,
12
- InvalidArgumentError,
13
- HeadersTimeoutError,
14
- BodyTimeoutError,
15
- ResponseExceededMaxSizeError
11
+ InformationalError
16
12
  } = require('../core/errors.js')
17
13
  const {
18
14
  kUrl,
@@ -29,40 +25,18 @@ const {
29
25
  kOnError,
30
26
  kMaxConcurrentStreams,
31
27
  kHTTP2Session,
32
- kHostAuthority,
33
28
  kResume,
34
29
  kSize,
35
- kHTTPContext,
36
- kClosed,
37
- kKeepAliveDefaultTimeout,
38
- kHeadersTimeout,
39
- kBodyTimeout,
40
- kEnableConnectProtocol,
41
- kRemoteSettings,
42
- kHTTP2Stream,
43
- kHTTP2SessionState,
44
- kHTTP2Options,
45
- kMaxResponseSize
30
+ kHTTPContext
46
31
  } = require('../core/symbols.js')
47
- const { channels } = require('../core/diagnostics.js')
48
32
 
49
33
  const kOpenStreams = Symbol('open streams')
50
- const kRequestStreamId = Symbol('request stream id')
51
- const kRequestStream = Symbol('request stream')
52
- const kRequestStreamCleanup = Symbol('request stream cleanup')
53
- const kRequestStreamState = Symbol('request stream state')
54
- const kReceivedGoAway = Symbol('received goaway')
55
- const kGoAwayReplayAttempts = Symbol('goaway replay attempts')
56
- const kRefusedStreamRetry = Symbol('refused stream retry')
57
-
58
- // RFC 9113 section 8.7: a client SHOULD NOT automatically retry a request more
59
- // than once. Without a budget a peer that keeps refusing turns one request into
60
- // an unbounded connect/refuse/reconnect loop that never settles and starves the
61
- // event loop.
62
- const MAX_GOAWAY_REPLAY_ATTEMPTS = 1
63
34
 
64
35
  let extractBody
65
36
 
37
+ // Experimental
38
+ let h2ExperimentalWarned = false
39
+
66
40
  /** @type {import('http2')} */
67
41
  let http2
68
42
  try {
@@ -80,1032 +54,293 @@ const {
80
54
  HTTP2_HEADER_SCHEME,
81
55
  HTTP2_HEADER_CONTENT_LENGTH,
82
56
  HTTP2_HEADER_EXPECT,
83
- HTTP2_HEADER_STATUS,
84
- HTTP2_HEADER_PROTOCOL,
85
- NGHTTP2_NO_ERROR,
86
- NGHTTP2_REFUSED_STREAM
57
+ HTTP2_HEADER_STATUS
87
58
  }
88
59
  } = http2
89
60
 
90
- function getGoAwayError (session, errorCode) {
91
- return session[kError] ||
92
- (errorCode === NGHTTP2_NO_ERROR
93
- ? new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`)
94
- : new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(session[kSocket])))
95
- }
96
-
97
- function resetHttp2Session (session, err) {
98
- const client = session[kClient]
99
- const socket = session[kSocket]
100
-
101
- if (client[kHTTP2Session] === session) {
102
- client[kSocket] = null
103
- client[kHTTPContext] = null
104
- client[kHTTP2Session] = null
105
- }
106
-
107
- if (socket != null && socket[kError] == null) {
108
- socket[kError] = err
109
- }
110
-
111
- if (!session.closed && !session.destroyed) {
112
- try {
113
- session.destroy(err)
114
- } catch {}
115
- }
116
-
117
- util.destroy(socket, err)
118
- }
119
-
120
- function getGoAwayPendingIdx (client, lastStreamID) {
121
- const maxAcceptedStreamID = Number.isInteger(lastStreamID) ? lastStreamID : Number.MAX_SAFE_INTEGER
122
-
123
- for (let i = client[kRunningIdx]; i < client[kPendingIdx]; i++) {
124
- const request = client[kQueue][i]
125
-
126
- if (request == null) {
127
- continue
128
- }
129
-
130
- if (typeof request[kRequestStreamId] !== 'number' || request[kRequestStreamId] > maxAcceptedStreamID) {
131
- return i
61
+ function parseH2Headers (headers) {
62
+ const result = []
63
+
64
+ for (const [name, value] of Object.entries(headers)) {
65
+ // h2 may concat the header value by array
66
+ // e.g. Set-Cookie
67
+ if (Array.isArray(value)) {
68
+ for (const subvalue of value) {
69
+ // we need to provide each header value of header name
70
+ // because the headers handler expect name-value pair
71
+ result.push(Buffer.from(name), Buffer.from(subvalue))
72
+ }
73
+ } else {
74
+ result.push(Buffer.from(name), Buffer.from(value))
132
75
  }
133
76
  }
134
77
 
135
- return client[kPendingIdx]
136
- }
137
-
138
- function detachRequestFromStream (request) {
139
- request[kRequestStreamId] = null
140
- request[kRequestStream] = null
141
- request[kRequestStreamCleanup] = null
78
+ return result
142
79
  }
143
80
 
144
- function bindRequestToStream (request, stream, cleanup) {
145
- const previousCleanup = request[kRequestStreamCleanup]
146
- const previousStream = request[kRequestStream]
147
- detachRequestFromStream(request)
148
- previousCleanup?.(previousStream)
149
- request[kRequestStreamId] = stream.id
150
- request[kRequestStream] = stream
151
- request[kRequestStreamCleanup] = cleanup
152
- }
153
-
154
- function clearRequestStream (request) {
155
- const cleanup = request[kRequestStreamCleanup]
156
- const stream = request[kRequestStream]
157
- detachRequestFromStream(request)
158
- cleanup?.(stream)
159
- }
160
-
161
- function requeueUnsentRequest (client, request) {
162
- client[kQueue].splice(client[kPendingIdx] + 1, 0, request)
81
+ /**
82
+ * @param {import('node:http2').IncomingHttpHeaders} headers
83
+ * @returns {Buffer[]}
84
+ */
85
+ function parseH2ResponseHeaders (headers) {
86
+ const { [HTTP2_HEADER_STATUS]: _statusCode, ...realHeaders } = headers
87
+ return parseH2Headers(realHeaders)
163
88
  }
164
89
 
165
- function completeRequest (client, request, resetPendingIdx = false) {
166
- const queue = client[kQueue]
167
- const runningIdx = client[kRunningIdx]
168
-
169
- // In-order completion: clear the request and advance without splicing.
170
- // The client's resume loop compacts cleared slots once the index grows.
171
- if (runningIdx < client[kPendingIdx] && queue[runningIdx] === request) {
172
- queue[runningIdx] = null
173
- client[kRunningIdx] = runningIdx + 1
174
- return
175
- }
176
-
177
- const index = queue.indexOf(request, runningIdx)
178
-
179
- if (index === -1 || index >= client[kPendingIdx]) {
180
- return
181
- }
182
-
183
- queue.splice(index, 1)
184
- client[kPendingIdx]--
90
+ async function connectH2 (client, socket) {
91
+ client[kSocket] = socket
185
92
 
186
- if (resetPendingIdx && client[kPendingIdx] < client[kRunningIdx]) {
187
- client[kPendingIdx] = client[kRunningIdx]
93
+ if (!h2ExperimentalWarned) {
94
+ h2ExperimentalWarned = true
95
+ process.emitWarning('H2 support is experimental, expect them to change at any time.', {
96
+ code: 'UNDICI-H2'
97
+ })
188
98
  }
189
- }
190
-
191
- function canReplayRequest (request) {
192
- const { body } = request
193
99
 
194
- return body == null || util.isBuffer(body) || util.isBlobLike(body)
195
- }
100
+ const session = http2.connect(client[kUrl], {
101
+ createConnection: () => socket,
102
+ peerMaxConcurrentStreams: client[kMaxConcurrentStreams]
103
+ })
196
104
 
197
- function hasResponseStarted (request) {
198
- const state = request[kRequestStream]?.[kRequestStreamState]
199
- return state?.responseReceived === true
200
- }
105
+ session[kOpenStreams] = 0
106
+ session[kClient] = client
107
+ session[kSocket] = socket
201
108
 
202
- // Count a GOAWAY refusal against the request's replay budget. A peer that
203
- // refuses every connection must eventually surface an error to the caller
204
- // rather than being retried forever. Kept separate from canReplayRequest so
205
- // that the REFUSED_STREAM retry, which has its own single-attempt limit, does
206
- // not consume this budget just by asking whether the body can be replayed.
207
- function registerGoAwayRefusal (request) {
208
- const attempts = (request[kGoAwayReplayAttempts] ?? 0) + 1
209
- request[kGoAwayReplayAttempts] = attempts
109
+ util.addListener(session, 'error', onHttp2SessionError)
110
+ util.addListener(session, 'frameError', onHttp2FrameError)
111
+ util.addListener(session, 'end', onHttp2SessionEnd)
112
+ util.addListener(session, 'goaway', onHTTP2GoAway)
113
+ util.addListener(session, 'close', function () {
114
+ const { [kClient]: client } = this
115
+ const { [kSocket]: socket } = client
210
116
 
211
- return attempts <= MAX_GOAWAY_REPLAY_ATTEMPTS
212
- }
117
+ const err = this[kSocket][kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket))
213
118
 
214
- function closeStream (stream, code = NGHTTP2_REFUSED_STREAM) {
215
- if (stream != null && !stream.destroyed && !stream.closed) {
216
- try {
217
- stream.close(code)
218
- } catch {}
219
- }
220
- }
119
+ client[kHTTP2Session] = null
221
120
 
222
- function detachRequestStreamForClose (request) {
223
- const stream = request[kRequestStream]
121
+ if (client.destroyed) {
122
+ assert(client[kPending] === 0)
224
123
 
225
- clearRequestStream(request)
226
- severRequestStream(stream)
124
+ // Fail entire queue.
125
+ const requests = client[kQueue].splice(client[kRunningIdx])
126
+ for (let i = 0; i < requests.length; i++) {
127
+ const request = requests[i]
128
+ util.errorRequest(client, request, err)
129
+ }
130
+ }
131
+ })
227
132
 
228
- return stream
229
- }
133
+ session.unref()
230
134
 
231
- // Unbind a stream from its request for good. releaseRequestStream() alone
232
- // leaves the 'close' listener attached and kRequestStreamState populated, so a
233
- // stream abandoned here would still run completeRequestStream() later — and
234
- // splice out the request that has since been requeued onto another session.
235
- function severRequestStream (stream) {
236
- if (stream == null || stream[kRequestStreamState] == null) {
237
- return
238
- }
135
+ client[kHTTP2Session] = session
136
+ socket[kHTTP2Session] = session
239
137
 
240
- stream[kRequestStreamState] = null
241
- stream.off('close', completeRequestStream)
242
- // Upgrade streams use their own close cleanup, which would otherwise release
243
- // the session a second time after the stream has been severed for GOAWAY.
244
- stream.off('close', onUpgradeStreamClose)
138
+ util.addListener(socket, 'error', function (err) {
139
+ assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
245
140
 
246
- if (stream[kHTTP2Session] != null) {
247
- closeStreamSession(stream)
248
- }
141
+ this[kError] = err
249
142
 
250
- if (!stream.destroyed && !stream.closed) {
251
- stream.once('error', noop)
252
- }
253
- }
143
+ this[kClient][kOnError](err)
144
+ })
254
145
 
255
- function connectH2 (client, socket) {
256
- client[kSocket] = socket
146
+ util.addListener(socket, 'end', function () {
147
+ util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this)))
148
+ })
257
149
 
258
- const http2InitialWindowSize = client[kHTTP2Options].sessionOptions?.initialWindowSize
259
- const http2ConnectionWindowSize = client[kHTTP2Options].connectionWindowSize
150
+ util.addListener(socket, 'close', function () {
151
+ const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
260
152
 
261
- const session = http2.connect(client[kUrl], {
262
- createConnection: () => socket,
263
- peerMaxConcurrentStreams: client[kHTTP2Options].maxConcurrentStreams,
264
- settings: {
265
- // TODO(metcoder95): add support for PUSH
266
- enablePush: false,
267
- ...(http2InitialWindowSize != null ? { initialWindowSize: http2InitialWindowSize } : null)
268
- }
269
- })
153
+ client[kSocket] = null
270
154
 
271
- client[kSocket] = socket
272
- session[kOpenStreams] = 0
273
- session[kClient] = client
274
- session[kSocket] = socket
275
- session[kHTTP2SessionState] = {
276
- idleTimeout: null,
277
- // Armed while the peer advertises MAX_CONCURRENT_STREAMS = 0 and we have
278
- // work that cannot start. See setNoStreamsTimeout.
279
- noStreamsTimeout: null,
280
- // Sockets start out ref'd. Session ref/unref proxies to the socket, so a
281
- // single cached flag lets us skip redundant uv ref/unref calls, provided
282
- // every ref/unref of the session or its socket goes through
283
- // refH2Session/unrefH2Session.
284
- refed: true,
285
- ping: {
286
- interval: client[kHTTP2Options].pingInterval === 0 ? null : setInterval(onHttp2SendPing, client[kHTTP2Options].pingInterval, session).unref()
155
+ if (this[kHTTP2Session] != null) {
156
+ this[kHTTP2Session].destroy(err)
287
157
  }
288
- }
289
- session[kReceivedGoAway] = false
290
- // We set it to true by default in a best-effort; however once connected to an H2 server
291
- // we will check if extended CONNECT protocol is supported or not
292
- // and set this value accordingly.
293
- session[kEnableConnectProtocol] = false
294
- // States whether or not we have received the remote settings from the server
295
- session[kRemoteSettings] = false
296
-
297
- // Apply connection-level flow control once connected (if supported).
298
- if (http2ConnectionWindowSize) {
299
- util.addListener(session, 'connect', applyConnectionWindowSize.bind(session, http2ConnectionWindowSize))
300
- }
301
158
 
302
- util.addListener(session, 'error', onHttp2SessionError)
303
- util.addListener(session, 'frameError', onHttp2FrameError)
304
- util.addListener(session, 'goaway', onHttp2SessionGoAway)
305
- util.addListener(session, 'close', onHttp2SessionClose)
306
- util.addListener(session, 'remoteSettings', onHttp2RemoteSettings)
307
- // TODO (@metcoder95): implement SETTINGS support
308
- // util.addListener(session, 'localSettings', onHttp2RemoteSettings)
159
+ client[kPendingIdx] = client[kRunningIdx]
309
160
 
310
- unrefH2Session(session)
161
+ assert(client[kRunning] === 0)
311
162
 
312
- client[kHTTP2Session] = session
313
- socket[kHTTP2Session] = session
163
+ client.emit('disconnect', client[kUrl], [client], err)
314
164
 
315
- util.addListener(socket, 'error', onHttp2SocketError)
316
- util.addListener(socket, 'end', onHttp2SocketEnd)
317
- util.addListener(socket, 'close', onHttp2SocketClose)
165
+ client[kResume]()
166
+ })
318
167
 
319
- socket[kClosed] = false
320
- socket.on('close', onSocketClose)
168
+ let closed = false
169
+ socket.on('close', () => {
170
+ closed = true
171
+ })
321
172
 
322
173
  return {
323
174
  version: 'h2',
324
175
  defaultPipelining: Infinity,
325
- /**
326
- * @param {import('../core/request.js')} request
327
- * @returns {boolean}
328
- */
329
- write (request) {
330
- return writeH2(client, request)
176
+ write (...args) {
177
+ return writeH2(client, ...args)
331
178
  },
332
- /**
333
- * @returns {void}
334
- */
335
179
  resume () {
336
180
  resumeH2(client)
337
181
  },
338
- /**
339
- * @param {Error | null} err
340
- * @param {() => void} callback
341
- */
342
182
  destroy (err, callback) {
343
- if (socket[kClosed]) {
183
+ if (closed) {
344
184
  queueMicrotask(callback)
345
185
  } else {
186
+ // Destroying the socket will trigger the session close
346
187
  socket.destroy(err).on('close', callback)
347
188
  }
348
189
  },
349
- /**
350
- * @type {boolean}
351
- */
352
190
  get destroyed () {
353
191
  return socket.destroyed
354
192
  },
355
- /**
356
- * @param {import('../core/request.js')} request
357
- * @returns {boolean}
358
- */
359
- busy (request) {
360
- if (session[kRemoteSettings] === false && client[kRunning] > 0) {
361
- return true
362
- }
363
-
364
- if (client[kRunning] >= client[kMaxConcurrentStreams]) {
365
- return true
366
- }
367
-
368
- if (request != null) {
369
- if (client[kRunning] > 0) {
370
- // We are already processing requests
371
-
372
- // Unlike HTTP/1.1 pipelining, HTTP/2 multiplexes requests on
373
- // independent streams, so non-idempotent requests can be dispatched
374
- // concurrently. Retry eligibility is handled by stream/session error
375
- // handling instead of by serializing all non-idempotent requests.
376
- // Don't dispatch an upgrade until all preceding requests have completed.
377
- // Possibly, we do not have remote settings confirmed yet.
378
- if ((request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false) return true
379
- } else {
380
- return (request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false
381
- }
382
- }
383
-
193
+ busy () {
384
194
  return false
385
- }
386
- }
387
- }
388
-
389
- // Session ref/unref proxies to the underlying socket, so refH2Session and
390
- // unrefH2Session cover both and can skip the call when the cached ref state
391
- // already matches.
392
- function refH2Session (session) {
393
- const state = session[kHTTP2SessionState]
394
-
395
- if (state.refed === false) {
396
- state.refed = true
397
- session.ref()
398
- }
399
- }
400
-
401
- function unrefH2Session (session) {
402
- const state = session[kHTTP2SessionState]
403
-
404
- if (state.refed === true) {
405
- state.refed = false
406
- session.unref()
407
- }
408
- }
409
-
410
- function resumeH2 (client) {
411
- const socket = client[kSocket]
412
- const session = client[kHTTP2Session]
413
-
414
- if (socket?.destroyed === false) {
415
- // After an upgrade the queue is empty but its stream is still in use, so never unref while a stream is open.
416
- if (session[kOpenStreams] === 0 && client[kSize] === 0) {
417
- unrefH2Session(session)
418
- } else {
419
- refH2Session(session)
420
- }
421
-
422
- if (client[kSize] === 0 && session[kOpenStreams] === 0) {
423
- setHttp2IdleTimeout(session)
424
- } else {
425
- clearHttp2IdleTimeout(session)
426
- }
427
-
428
- if (client[kMaxConcurrentStreams] === 0 && client[kRunning] === 0 && client[kPending] > 0) {
429
- setNoStreamsTimeout(session)
430
- } else {
431
- clearNoStreamsTimeout(session)
432
- }
433
- }
434
- }
435
-
436
- function clearNoStreamsTimeout (session) {
437
- const state = session[kHTTP2SessionState]
438
-
439
- if (state?.noStreamsTimeout != null) {
440
- clearTimeout(state.noStreamsTimeout)
441
- state.noStreamsTimeout = null
442
- }
443
- }
444
-
445
- // A peer is allowed to advertise SETTINGS_MAX_CONCURRENT_STREAMS = 0 to refuse
446
- // new streams (RFC 9113 §6.5.2), and is expected to raise it again later. Until
447
- // it does, busy() reports the client as permanently busy and queued requests
448
- // cannot open a stream — which means no per-stream timeout covers them, and no
449
- // reconnect can happen either, so the SETTINGS frame that would lift the limit
450
- // can never arrive. Give the peer headersTimeout to start honouring requests
451
- // before failing them; a request that cannot even be sent has missed the same
452
- // deadline as one whose headers never arrive.
453
- function setNoStreamsTimeout (session) {
454
- const client = session[kClient]
455
- const state = session[kHTTP2SessionState]
456
- const timeout = client[kHeadersTimeout]
457
-
458
- if (!timeout || state.noStreamsTimeout != null) {
459
- return
460
- }
461
-
462
- state.noStreamsTimeout = setTimeout(onNoStreamsTimeout, timeout, session).unref()
463
- }
464
-
465
- function onNoStreamsTimeout (session) {
466
- const client = session[kClient]
467
- const state = session[kHTTP2SessionState]
468
-
469
- state.noStreamsTimeout = null
470
-
471
- if (
472
- client[kHTTP2Session] !== session ||
473
- client[kMaxConcurrentStreams] !== 0 ||
474
- client[kRunning] !== 0 ||
475
- client[kPending] === 0
476
- ) {
477
- return
478
- }
479
-
480
- const err = new HeadersTimeoutError(
481
- `HTTP/2: server did not accept a new stream within ${client[kHeadersTimeout]}`
482
- )
483
-
484
- const requests = client[kQueue].splice(client[kPendingIdx])
485
- for (let i = 0; i < requests.length; i++) {
486
- if (requests[i] != null) {
487
- util.errorRequest(client, requests[i], err)
488
- }
489
- }
490
-
491
- // Drop the unusable session so the next request gets a fresh connection,
492
- // whose SETTINGS may well allow streams again.
493
- session[kError] = err
494
- resetHttp2Session(session, err)
495
- }
496
-
497
- function clearHttp2IdleTimeout (session) {
498
- const state = session[kHTTP2SessionState]
499
-
500
- if (state?.idleTimeout != null) {
501
- clearTimeout(state.idleTimeout)
502
- state.idleTimeout = null
503
- }
504
- }
505
-
506
- function setHttp2IdleTimeout (session) {
507
- const client = session[kClient]
508
-
509
- if (client[kHTTP2Session] !== session || session.closed || session.destroyed) {
510
- return
511
- }
512
-
513
- if (session[kOpenStreams] !== 0 || client[kSize] !== 0) {
514
- clearHttp2IdleTimeout(session)
515
- return
516
- }
517
-
518
- const state = session[kHTTP2SessionState]
519
- if (state.idleTimeout == null) {
520
- state.idleTimeout = setTimeout(onHttp2SessionIdleTimeout, client[kKeepAliveDefaultTimeout], session).unref()
521
- }
522
- }
523
-
524
- function onHttp2SessionIdleTimeout (session) {
525
- const client = session[kClient]
526
- const socket = session[kSocket]
527
- const state = session[kHTTP2SessionState]
528
-
529
- state.idleTimeout = null
530
-
531
- if (client[kHTTP2Session] !== session || session[kOpenStreams] !== 0 || client[kSize] !== 0 || session.closed || session.destroyed) {
532
- return
533
- }
534
-
535
- const err = new InformationalError('socket idle timeout')
536
- socket[kError] = err
537
- util.destroy(socket, err)
538
- }
539
-
540
- function applyConnectionWindowSize (connectionWindowSize) {
541
- try {
542
- if (typeof this.setLocalWindowSize === 'function') {
543
- this.setLocalWindowSize(connectionWindowSize)
544
- }
545
- } catch {
546
- // Best-effort only.
547
- }
548
- }
549
-
550
- function onHttp2RemoteSettings (settings) {
551
- // Fallbacks are a safe bet, remote setting will always override
552
- this[kClient][kMaxConcurrentStreams] = settings.maxConcurrentStreams ?? this[kClient][kMaxConcurrentStreams]
553
- /**
554
- * From RFC-8441
555
- * A sender MUST NOT send a SETTINGS_ENABLE_CONNECT_PROTOCOL parameter
556
- * with the value of 0 after previously sending a value of 1.
557
- */
558
- // Note: Cannot be tested in Node, it does not supports disabling the extended CONNECT protocol once enabled
559
- if (this[kRemoteSettings] === true && this[kEnableConnectProtocol] === true && settings.enableConnectProtocol === false) {
560
- const err = new InformationalError('HTTP/2: Server disabled extended CONNECT protocol against RFC-8441')
561
- this[kSocket][kError] = err
562
- this[kClient][kOnError](err)
563
- return
564
- }
565
-
566
- this[kEnableConnectProtocol] = settings.enableConnectProtocol ?? this[kEnableConnectProtocol]
567
- this[kRemoteSettings] = true
568
- this[kClient][kResume]()
569
- }
570
-
571
- function onHttp2SendPing (session) {
572
- const state = session[kHTTP2SessionState]
573
- if ((session.closed || session.destroyed) && state.ping.interval != null) {
574
- clearInterval(state.ping.interval)
575
- state.ping.interval = null
576
- return
577
- }
578
-
579
- // If no ping sent, do nothing
580
- session.ping(onPing.bind(session))
581
-
582
- function onPing (err, duration) {
583
- const client = this[kClient]
584
- const socket = this[kSocket]
585
-
586
- if (err != null) {
587
- const error = new InformationalError(`HTTP/2: "PING" errored - type ${err.message}`)
588
- socket[kError] = error
589
- client[kOnError](error)
590
- } else {
591
- client.emit('ping', duration)
592
- }
593
- }
594
- }
595
-
596
- function onHttp2SessionError (err) {
597
- assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
598
-
599
- this[kSocket][kError] = err
600
-
601
- if (this[kReceivedGoAway]) {
602
- return
603
- }
604
-
605
- this[kClient][kOnError](err)
606
- }
607
-
608
- function onHttp2FrameError (type, code, id) {
609
- if (id === 0) {
610
- if (this[kReceivedGoAway]) {
611
- return
612
- }
613
-
614
- const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
615
- this[kSocket][kError] = err
616
- this[kClient][kOnError](err)
617
- }
618
- }
619
-
620
- /**
621
- * This is the root cause of #3011
622
- * We need to handle GOAWAY frames properly, and trigger the session close
623
- * along with the socket right away
624
- *
625
- * @this {import('http2').ClientHttp2Session}
626
- * @param {number} errorCode
627
- * @param {number} lastStreamID
628
- */
629
- function onHttp2SessionGoAway (errorCode, lastStreamID) {
630
- if (this[kReceivedGoAway]) {
631
- return
632
- }
633
-
634
- this[kReceivedGoAway] = true
635
-
636
- const err = getGoAwayError(this, errorCode)
637
- const client = this[kClient]
638
- const previousPendingIdx = client[kPendingIdx]
639
- const pendingIdx = getGoAwayPendingIdx(client, lastStreamID)
640
- const retriableRequests = []
641
- const streamsToClose = []
642
-
643
- // Closing one stream after GOAWAY can synchronously emit frameError on
644
- // sibling streams. Detach all affected requests first so those errors do
645
- // not fail requests that are about to be requeued.
646
- for (let i = pendingIdx; i < previousPendingIdx; i++) {
647
- const request = client[kQueue][i]
648
-
649
- if (request != null) {
650
- // Read before detaching, which drops the stream state.
651
- const responseStarted = hasResponseStarted(request)
652
-
653
- streamsToClose.push(detachRequestStreamForClose(request))
654
-
655
- if (!responseStarted && canReplayRequest(request) && registerGoAwayRefusal(request)) {
656
- retriableRequests.push(request)
657
- } else {
658
- util.errorRequest(client, request, err)
659
- }
660
- }
661
- }
662
-
663
- for (let i = 0; i < streamsToClose.length; i++) {
664
- closeStream(streamsToClose[i])
665
- }
666
-
667
- if (pendingIdx !== previousPendingIdx) {
668
- const remainingPendingRequests = client[kQueue].slice(previousPendingIdx)
669
- client[kQueue].length = pendingIdx
670
- client[kQueue].push(...retriableRequests, ...remainingPendingRequests)
671
- }
672
-
673
- if (client[kHTTP2Session] === this) {
674
- client[kSocket] = null
675
- client[kHTTPContext] = null
676
- client[kHTTP2Session] = null
677
- }
678
-
679
- clearHttp2IdleTimeout(this)
680
- clearNoStreamsTimeout(this)
681
-
682
- if (!this.closed && !this.destroyed) {
683
- this.close()
684
- }
685
-
686
- client[kPendingIdx] = pendingIdx
687
-
688
- client.emit('disconnect', client[kUrl], [client], err)
689
-
690
- client[kResume]()
691
- }
692
-
693
- function onHttp2SessionClose () {
694
- const { [kClient]: client, [kHTTP2SessionState]: state, [kSocket]: socket } = this
695
-
696
- const err = socket[kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket))
697
-
698
- if (client[kHTTP2Session] === this) {
699
- client[kSocket] = null
700
- client[kHTTPContext] = null
701
- client[kHTTP2Session] = null
702
- }
703
-
704
- clearHttp2IdleTimeout(this)
705
- clearNoStreamsTimeout(this)
706
-
707
- if (state.ping.interval != null) {
708
- clearInterval(state.ping.interval)
709
- state.ping.interval = null
710
- }
711
-
712
- if (client.destroyed) {
713
- assert(client[kPending] === 0)
714
-
715
- // Fail entire queue.
716
- const requests = client[kQueue].splice(client[kRunningIdx])
717
- for (let i = 0; i < requests.length; i++) {
718
- const request = requests[i]
719
- if (request != null) {
720
- util.errorRequest(client, request, err)
721
- }
722
- }
723
- }
724
- }
725
-
726
- function onHttp2SocketClose () {
727
- const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
728
-
729
- const session = this[kHTTP2Session]
730
- const client = session[kClient]
731
-
732
- if (client[kSocket] !== this) {
733
- // Ignore stale socket closes from a detached GOAWAY session and from any
734
- // session that has already been replaced. If the session was detached
735
- // without a GOAWAY and there is no replacement yet, we still need the
736
- // close event to flush the client state.
737
- if (session[kReceivedGoAway] || (client[kHTTP2Session] != null && client[kHTTP2Session] !== session)) {
738
- return
739
- }
740
- }
741
-
742
- client[kSocket] = null
743
- client[kHTTPContext] = null
744
- if (client[kHTTP2Session] === session) {
745
- client[kHTTP2Session] = null
746
- }
747
-
748
- session.destroy(err)
749
-
750
- client[kPendingIdx] = client[kRunningIdx]
751
-
752
- assert(client[kRunning] === 0)
753
-
754
- client.emit('disconnect', client[kUrl], [client], err)
755
-
756
- client[kResume]()
757
- }
758
-
759
- function onHttp2SocketError (err) {
760
- assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
761
-
762
- this[kError] = err
763
-
764
- if (this[kHTTP2Session]?.[kReceivedGoAway]) {
765
- return
766
- }
767
-
768
- this[kHTTP2Session]?.[kClient]?.[kOnError](err)
769
- }
770
-
771
- function onHttp2SocketEnd () {
772
- util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this)))
773
- }
774
-
775
- function onSocketClose () {
776
- this[kClosed] = true
777
- }
778
-
779
- function noop () {}
780
-
781
- function closeStreamSession (stream) {
782
- const session = stream[kHTTP2Session]
783
- const client = session[kClient]
784
-
785
- stream[kHTTP2Session] = null
786
- session[kOpenStreams] -= 1
787
- // A session that received GOAWAY does not need to stay ref'd for queued requests.
788
- if (session[kOpenStreams] === 0 && (client[kSize] === 0 || session[kReceivedGoAway])) {
789
- unrefH2Session(session)
790
- setHttp2IdleTimeout(session)
791
- }
792
- }
793
-
794
- function onUpgradeStreamClose () {
795
- this.off('error', noop)
796
-
797
- const state = this[kRequestStreamState]
798
- this[kRequestStreamState] = null
799
-
800
- failUpgradeStream(state, new InformationalError('HTTP/2: stream closed before response headers'))
801
- closeStreamSession(this)
802
- }
803
-
804
- // Idempotent terminal cleanup, called from both 'end' and 'close': the
805
- // null-state guard no-ops the later call.
806
- function completeRequestStream () {
807
- const state = this[kRequestStreamState]
808
-
809
- if (state == null) {
810
- return
811
- }
812
-
813
- // Release the stream first so request references are cleared,
814
- // then complete the response with trailers if available.
815
- releaseRequestStream(this)
816
-
817
- if (state.pendingEnd && !state.request.aborted && !state.request.completed) {
818
- state.request.onResponseEnd(state.trailers || {})
819
- } else if (!state.request.aborted && !state.request.completed) {
820
- // The stream closed without a complete response and without reporting an
821
- // error. finalizeRequest() below frees the queue slot either way, so
822
- // without this the request would simply vanish and its caller would never
823
- // hear back.
824
- util.errorRequest(
825
- state.client,
826
- state.request,
827
- new InformationalError('HTTP/2: stream closed before the response was complete')
828
- )
829
- }
830
-
831
- finalizeRequest(state)
832
- closeStreamSession(this)
833
- this[kRequestStreamState] = null
834
- }
835
-
836
- // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
837
- function shouldSendContentLength (method) {
838
- return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
839
- }
840
-
841
- function buildRequestHeaders (reqHeaders) {
842
- const headers = {}
843
-
844
- for (let n = 0; n < reqHeaders.length; n += 2) {
845
- const key = reqHeaders[n + 0]
846
- const val = reqHeaders[n + 1]
847
- const current = headers[key]
848
-
849
- if (key === 'cookie') {
850
- if (current != null) {
851
- headers[key] = Array.isArray(current) ? (current.push(val), current) : [current, val]
852
- } else {
853
- headers[key] = val
854
- }
855
-
856
- continue
857
- }
858
-
859
- if (typeof val === 'string') {
860
- headers[key] = current ? `${current}, ${val}` : val
861
- continue
862
- }
863
-
864
- for (let i = 0; i < val.length; i++) {
865
- headers[key] = headers[key] ? `${headers[key]}, ${val[i]}` : val[i]
866
- }
867
- }
868
-
869
- return headers
870
- }
871
-
872
- function removeUpgradeStreamListeners (stream) {
873
- stream.off('response', onUpgradeResponse)
874
- stream.off('error', onUpgradeStreamError)
875
- stream.off('end', onUpgradeStreamEnd)
876
- stream.off('timeout', onUpgradeStreamTimeout)
877
- stream.off('error', noop)
878
- }
879
-
880
- function releaseUpgradeStream (stream) {
881
- if (stream == null) {
882
- return
883
- }
884
-
885
- const state = stream[kRequestStreamState]
886
- if (state == null) {
887
- return
888
- }
889
-
890
- const { request } = state
891
-
892
- if (request[kRequestStream] === stream) {
893
- detachRequestFromStream(request)
894
- }
895
-
896
- removeUpgradeStreamListeners(stream)
897
-
898
- if (!stream.destroyed && !stream.closed) {
899
- stream.once('error', noop)
900
- }
901
- }
902
-
903
- function failUpgradeStream (state, err) {
904
- if (state == null) {
905
- return
906
- }
907
-
908
- const { request } = state
909
- if (state.responseReceived || request.aborted || request.completed) {
910
- return
195
+ }
911
196
  }
912
-
913
- releaseUpgradeStream(state.stream)
914
- state.abort(err, true)
915
197
  }
916
198
 
917
- function onUpgradeStreamError () {
918
- const state = this[kRequestStreamState]
199
+ function resumeH2 (client) {
200
+ const socket = client[kSocket]
919
201
 
920
- if (typeof this.rstCode === 'number' && this.rstCode !== 0) {
921
- failUpgradeStream(state, new InformationalError(`HTTP/2: "stream error" received - code ${this.rstCode}`))
922
- } else {
923
- failUpgradeStream(state, new InformationalError('HTTP/2: stream errored before response headers'))
202
+ if (socket?.destroyed === false) {
203
+ if (client[kSize] === 0 && client[kMaxConcurrentStreams] === 0) {
204
+ socket.unref()
205
+ client[kHTTP2Session].unref()
206
+ } else {
207
+ socket.ref()
208
+ client[kHTTP2Session].ref()
209
+ }
924
210
  }
925
211
  }
926
212
 
927
- function onUpgradeStreamEnd () {
928
- failUpgradeStream(this[kRequestStreamState], new InformationalError('HTTP/2: stream half-closed (remote)'))
929
- }
213
+ function onHttp2SessionError (err) {
214
+ assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
930
215
 
931
- function onUpgradeStreamTimeout () {
932
- const state = this[kRequestStreamState]
933
- failUpgradeStream(state, new InformationalError(`HTTP/2: "stream timeout after ${state.headersTimeout}"`))
216
+ this[kSocket][kError] = err
217
+ this[kClient][kOnError](err)
934
218
  }
935
219
 
936
- function onUpgradeResponse (headers, _flags) {
937
- const stream = this
938
- const state = stream[kRequestStreamState]
939
- const { request } = state
940
-
941
- state.responseReceived = true
942
-
943
- const statusCode = headers[HTTP2_HEADER_STATUS]
944
- delete headers[HTTP2_HEADER_STATUS]
945
-
946
- try {
947
- request.onRequestUpgrade(statusCode, headers, stream)
948
- } catch (err) {
949
- state.abort(err)
950
- return
951
- }
952
-
953
- if (request.aborted) {
954
- return
220
+ function onHttp2FrameError (type, code, id) {
221
+ if (id === 0) {
222
+ const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
223
+ this[kSocket][kError] = err
224
+ this[kClient][kOnError](err)
955
225
  }
956
-
957
- removeUpgradeStreamListeners(stream)
958
- detachRequestFromStream(request)
959
- finalizeRequest(state)
960
226
  }
961
227
 
962
- function setupUpgradeStream (stream, state) {
963
- const { request, headersTimeout, session } = state
964
-
965
- stream[kHTTP2Stream] = true
966
- stream[kHTTP2Session] = session
967
- stream[kRequestStreamState] = state
968
- state.stream = stream
228
+ function onHttp2SessionEnd () {
229
+ const err = new SocketError('other side closed', util.getSocketInfo(this[kSocket]))
230
+ this.destroy(err)
231
+ util.destroy(this[kSocket], err)
232
+ }
969
233
 
970
- bindRequestToStream(request, stream, releaseUpgradeStream)
971
- stream.once('response', onUpgradeResponse)
972
- stream.on('error', onUpgradeStreamError)
973
- stream.once('end', onUpgradeStreamEnd)
974
- stream.on('timeout', onUpgradeStreamTimeout)
975
- stream.once('close', onUpgradeStreamClose)
234
+ /**
235
+ * This is the root cause of #3011
236
+ * We need to handle GOAWAY frames properly, and trigger the session close
237
+ * along with the socket right away
238
+ */
239
+ function onHTTP2GoAway (code) {
240
+ // We cannot recover, so best to close the session and the socket
241
+ const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${code}`, util.getSocketInfo(this))
242
+ const client = this[kClient]
976
243
 
977
- clearHttp2IdleTimeout(session)
978
- ++session[kOpenStreams]
979
- stream.setTimeout(headersTimeout)
980
- }
244
+ client[kSocket] = null
245
+ client[kHTTPContext] = null
981
246
 
982
- function finalizeRequest (state, resetPendingIdx = false) {
983
- if (state.requestFinalized) {
984
- return
247
+ if (this[kHTTP2Session] != null) {
248
+ this[kHTTP2Session].destroy(err)
249
+ this[kHTTP2Session] = null
985
250
  }
986
251
 
987
- state.requestFinalized = true
988
- completeRequest(state.client, state.request, resetPendingIdx)
252
+ util.destroy(this[kSocket], err)
989
253
 
990
- state.client[kResume]()
991
- }
254
+ // Fail head of pipeline.
255
+ if (client[kRunningIdx] < client[kQueue].length) {
256
+ const request = client[kQueue][client[kRunningIdx]]
257
+ client[kQueue][client[kRunningIdx]++] = null
258
+ util.errorRequest(client, request, err)
259
+ client[kPendingIdx] = client[kRunningIdx]
260
+ }
992
261
 
993
- function openStream (client, request, session, abort, headers, options) {
994
- try {
995
- return session.request(headers, options)
996
- } catch (err) {
997
- // A GOAWAY'd session rejects new streams, same as an invalid session:
998
- // reset and requeue on a fresh connection rather than the destroy + abort
999
- // below, whose destroy(socket, err) can crash via an unhandled 'error'.
1000
- if (err?.code === 'ERR_HTTP2_INVALID_SESSION' || err?.code === 'ERR_HTTP2_GOAWAY_SESSION') {
1001
- const wrappedErr = new SocketError(err.message, util.getSocketInfo(session[kSocket]))
1002
- wrappedErr.cause = err
1003
- session[kError] = wrappedErr
1004
- resetHttp2Session(session, wrappedErr)
1005
- requeueUnsentRequest(client, request)
1006
-
1007
- return null
1008
- }
262
+ assert(client[kRunning] === 0)
1009
263
 
1010
- const wrappedErr = new InformationalError(err.message, { cause: err })
1011
- session[kError] = wrappedErr
1012
- session[kSocket][kError] = wrappedErr
264
+ client.emit('disconnect', client[kUrl], [client], err)
1013
265
 
1014
- session.destroy(wrappedErr)
1015
- util.destroy(session[kSocket], wrappedErr)
1016
- abort(wrappedErr)
266
+ client[kResume]()
267
+ }
1017
268
 
1018
- return null
1019
- }
269
+ // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
270
+ function shouldSendContentLength (method) {
271
+ return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
1020
272
  }
1021
273
 
1022
274
  function writeH2 (client, request) {
1023
- const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout]
1024
- const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout]
1025
275
  const session = client[kHTTP2Session]
1026
- const { method, path, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request
276
+ const { method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request
277
+ let { body } = request
1027
278
 
1028
- if (upgrade != null && upgrade !== 'websocket') {
1029
- util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`))
279
+ if (upgrade) {
280
+ util.errorRequest(client, request, new Error('Upgrade not supported for H2'))
1030
281
  return false
1031
282
  }
1032
283
 
1033
- const headers = buildRequestHeaders(reqHeaders)
1034
-
1035
- headers[HTTP2_HEADER_AUTHORITY] = host || client[kHostAuthority]
1036
- headers[HTTP2_HEADER_METHOD] = method
284
+ const headers = {}
285
+ for (let n = 0; n < reqHeaders.length; n += 2) {
286
+ const key = reqHeaders[n + 0]
287
+ const val = reqHeaders[n + 1]
1037
288
 
1038
- // Single pre-shaped state object shared by all stream event handlers.
1039
- // All fields are declared up-front so the object keeps a stable hidden
1040
- // class for the whole request lifetime.
1041
- const state = {
1042
- abort: null,
1043
- body: request.body,
1044
- bytesRead: 0,
1045
- client,
1046
- contentLength: null,
1047
- expectsPayload: false,
1048
- maxResponseSize: client[kMaxResponseSize],
1049
- request,
1050
- headersTimeout,
1051
- bodyTimeout,
1052
- requestFinalized: false,
1053
- responseContentLength: null,
1054
- responseReceived: false,
1055
- bodySent: false,
1056
- pendingEnd: false,
1057
- trailers: null,
1058
- session,
1059
- stream: null
289
+ if (Array.isArray(val)) {
290
+ for (let i = 0; i < val.length; i++) {
291
+ if (headers[key]) {
292
+ headers[key] += `,${val[i]}`
293
+ } else {
294
+ headers[key] = val[i]
295
+ }
296
+ }
297
+ } else {
298
+ headers[key] = val
299
+ }
1060
300
  }
1061
301
 
1062
- const abort = (err, resetPendingIdx = false) => {
1063
- if (request.aborted || request.completed) {
302
+ /** @type {import('node:http2').ClientHttp2Stream} */
303
+ let stream
304
+
305
+ const { hostname, port } = client[kUrl]
306
+
307
+ headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}`
308
+ headers[HTTP2_HEADER_METHOD] = method
309
+
310
+ /**
311
+ * @param {Error} [error]
312
+ */
313
+ const abort = (error) => {
314
+ if (request.aborted) {
1064
315
  return
1065
316
  }
1066
317
 
1067
- err = err || new RequestAbortedError()
318
+ if (request.completed) {
319
+ if (method === 'CONNECT' && stream != null) {
320
+ util.destroy(stream, error || new RequestAbortedError())
321
+ }
322
+ return
323
+ }
1068
324
 
1069
- util.errorRequest(client, request, err)
325
+ error = error || new RequestAbortedError()
1070
326
 
1071
- if (state.stream != null) {
1072
- clearRequestStream(request)
1073
-
1074
- // On Abort, we close the stream to send RST_STREAM frame.
1075
- const stream = state.stream
1076
- stream.close()
1077
-
1078
- // close() alone leaves cleanup waiting on the 'close' event; on a busy,
1079
- // long-lived multiplexed session that event can fail to fire, leaving the
1080
- // native Http2Stream (and the whole request graph it pins) alive for the
1081
- // session's life. Destroy the stream synchronously to release the handle
1082
- // deterministically. Deferring the destroy (e.g. via setImmediate) leaks
1083
- // the same way when the event loop is stalled and the callback never runs
1084
- // under abort churn (#5558); close() has already queued the RST_STREAM
1085
- // frame on the native session, so a synchronous destroy still sends it.
1086
- if (!stream.destroyed) {
1087
- util.destroy(stream)
1088
- }
327
+ util.errorRequest(client, request, error)
1089
328
 
1090
- // We move the running index to the next request
1091
- client[kOnError](err)
1092
- finalizeRequest(state, resetPendingIdx)
329
+ if (stream != null) {
330
+ util.destroy(stream, error)
1093
331
  }
1094
332
 
1095
333
  // We do not destroy the socket as we can continue using the session
1096
- // the stream gets destroyed and the session remains to create new streams
1097
- util.destroy(state.body, err)
334
+ // the stream get's destroyed and the session remains to create new streams
335
+ util.destroy(body, error)
336
+ client[kQueue][client[kRunningIdx]++] = null
337
+ client[kResume]()
1098
338
  }
1099
339
 
1100
- state.abort = abort
1101
-
1102
- /** @type {import('node:http2').ClientHttp2Stream} */
1103
- let stream = null
1104
-
1105
340
  try {
1106
341
  // We are already connected, streams are pending.
1107
342
  // We can call on connect, and wait for abort
1108
- request.onRequestStart(abort, null)
343
+ request.onConnect(abort)
1109
344
  } catch (err) {
1110
345
  util.errorRequest(client, request, err)
1111
346
  }
@@ -1114,59 +349,71 @@ function writeH2 (client, request) {
1114
349
  return false
1115
350
  }
1116
351
 
1117
- if (upgrade || method === 'CONNECT') {
1118
- refH2Session(session)
1119
-
1120
- if (upgrade === 'websocket') {
1121
- // We cannot upgrade to websocket if extended CONNECT protocol is not supported
1122
- if (session[kEnableConnectProtocol] === false) {
1123
- util.errorRequest(client, request, new InformationalError('HTTP/2: Extended CONNECT protocol not supported by server'))
1124
- unrefH2Session(session)
1125
- return false
1126
- }
352
+ if (method === 'CONNECT') {
353
+ session.ref()
354
+ // We disabled endStream to allow the user to write to the stream
355
+ stream = session.request(headers, { endStream: false, signal })
356
+ let upgradeResponseFinished = false
1127
357
 
1128
- // We force the method to CONNECT
1129
- // as per RFC-8441
1130
- // https://datatracker.ietf.org/doc/html/rfc8441#section-4
1131
- headers[HTTP2_HEADER_METHOD] = 'CONNECT'
1132
- headers[HTTP2_HEADER_PROTOCOL] = 'websocket'
1133
- // :path and :scheme headers must be omitted when sending CONNECT but set if extended-CONNECT
1134
- headers[HTTP2_HEADER_PATH] = path
358
+ /**
359
+ * @param {import('node:http2').IncomingHttpHeaders} headers
360
+ */
361
+ const onResponse = (headers) => {
362
+ upgradeResponseFinished = true
363
+ stream.off(errorMonitor, onUpgradeError)
364
+ request.onUpgradeResponse(Number(headers[HTTP2_HEADER_STATUS]), headers, parseH2ResponseHeaders)
365
+ }
1135
366
 
1136
- if (protocol === 'ws:' || protocol === 'wss:') {
1137
- headers[HTTP2_HEADER_SCHEME] = protocol === 'ws:' ? 'http' : 'https'
1138
- } else {
1139
- headers[HTTP2_HEADER_SCHEME] = protocol === 'http:' ? 'http' : 'https'
367
+ /**
368
+ * @param {Error} error
369
+ */
370
+ const onUpgradeError = (error) => {
371
+ upgradeResponseFinished = true
372
+ stream.off('response', onResponse)
373
+ request.onUpgradeError(error)
374
+ }
375
+
376
+ const onReady = () => {
377
+ try {
378
+ request.onUpgrade(null, null, stream)
379
+ } catch (error) {
380
+ stream.off('response', onResponse)
381
+ abort(error)
382
+ return
1140
383
  }
1141
384
 
1142
- stream = openStream(client, request, session, abort, headers, { endStream: false, signal })
1143
- if (stream == null) {
1144
- unrefH2Session(session)
1145
- return false
385
+ if (request.aborted) {
386
+ return
1146
387
  }
1147
- setupUpgradeStream(stream, state)
1148
- return true
1149
- }
1150
388
 
1151
- // TODO: consolidate once we support CONNECT properly
1152
- // NOTE: We are already connected, streams are pending, first request
1153
- // will create a new stream. We trigger a request to create the stream and wait until
1154
- // `ready` event is triggered
1155
- // We disabled endStream to allow the user to write to the stream
1156
- stream = openStream(client, request, session, abort, headers, { endStream: false, signal })
1157
- if (stream == null) {
1158
- unrefH2Session(session)
1159
- return false
389
+ stream.off('error', abort)
390
+ stream.once(errorMonitor, onUpgradeError)
391
+ client[kQueue][client[kRunningIdx]++] = null
1160
392
  }
1161
- setupUpgradeStream(stream, state)
393
+
394
+ stream.once('response', onResponse)
395
+ stream.once('error', abort)
396
+ ++session[kOpenStreams]
397
+ onReady()
398
+
399
+ stream.once('close', () => {
400
+ if (!upgradeResponseFinished && request.completed) {
401
+ stream.off('response', onResponse)
402
+ stream.off(errorMonitor, onUpgradeError)
403
+ request.onUpgradeError(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`))
404
+ }
405
+ session[kOpenStreams] -= 1
406
+ if (session[kOpenStreams] === 0) session.unref()
407
+ })
1162
408
 
1163
409
  return true
1164
410
  }
1165
411
 
1166
412
  // https://tools.ietf.org/html/rfc7540#section-8.3
1167
413
  // :path and :scheme headers must be omitted when sending CONNECT
414
+
1168
415
  headers[HTTP2_HEADER_PATH] = path
1169
- headers[HTTP2_HEADER_SCHEME] = protocol === 'http:' ? 'http' : 'https'
416
+ headers[HTTP2_HEADER_SCHEME] = 'https'
1170
417
 
1171
418
  // https://tools.ietf.org/html/rfc7231#section-4.3.1
1172
419
  // https://tools.ietf.org/html/rfc7231#section-4.3.2
@@ -1180,14 +427,9 @@ function writeH2 (client, request) {
1180
427
  const expectsPayload = (
1181
428
  method === 'PUT' ||
1182
429
  method === 'POST' ||
1183
- method === 'PATCH' ||
1184
- method === 'QUERY' ||
1185
- method === 'PROPFIND' ||
1186
- method === 'PROPPATCH'
430
+ method === 'PATCH'
1187
431
  )
1188
432
 
1189
- let body = state.body
1190
-
1191
433
  if (body && typeof body.read === 'function') {
1192
434
  // Try to read EOF in order to get length.
1193
435
  body.read(0)
@@ -1209,12 +451,12 @@ function writeH2 (client, request) {
1209
451
  contentLength = request.contentLength
1210
452
  }
1211
453
 
1212
- if (contentLength === 0 && !expectsPayload) {
454
+ if (contentLength === 0 || !expectsPayload) {
1213
455
  // https://tools.ietf.org/html/rfc7230#section-3.3.2
1214
456
  // A user agent SHOULD NOT send a Content-Length header field when
1215
457
  // the request message does not contain a payload body and the method
1216
458
  // semantics do not anticipate such a body.
1217
- // And for methods that don't expect a payload, omit Content-Length.
459
+
1218
460
  contentLength = null
1219
461
  }
1220
462
 
@@ -1230,423 +472,172 @@ function writeH2 (client, request) {
1230
472
  }
1231
473
 
1232
474
  if (contentLength != null) {
1233
- assert(body || contentLength === 0, 'no body must not have content length')
475
+ assert(body, 'no body must not have content length')
1234
476
  headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`
1235
477
  }
1236
478
 
1237
- refH2Session(session)
1238
-
1239
- if (channels.sendHeaders.hasSubscribers) {
1240
- let header = ''
1241
- for (const key in headers) {
1242
- header += `${key}: ${headers[key]}\r\n`
1243
- }
1244
- channels.sendHeaders.publish({ request, headers: header, socket: session[kSocket] })
1245
- }
1246
-
1247
- // TODO(metcoder95): add support for sending trailers
1248
- const shouldEndStream = body === null || contentLength === 0
1249
-
1250
- state.body = body
1251
- state.contentLength = contentLength
1252
- state.expectsPayload = expectsPayload
479
+ session.ref()
1253
480
 
481
+ const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null
1254
482
  if (expectContinue) {
1255
483
  headers[HTTP2_HEADER_EXPECT] = '100-continue'
1256
- }
484
+ stream = session.request(headers, { endStream: shouldEndStream, signal })
1257
485
 
1258
- stream = openStream(client, request, session, abort, headers, { endStream: shouldEndStream, signal })
1259
- if (stream == null) {
1260
- return false
486
+ stream.once('continue', writeBodyH2)
487
+ } else {
488
+ stream = session.request(headers, {
489
+ endStream: shouldEndStream,
490
+ signal
491
+ })
492
+ writeBodyH2()
1261
493
  }
1262
- stream[kHTTP2Stream] = true
1263
- stream[kRequestStreamState] = state
1264
- state.stream = stream
1265
494
 
1266
495
  // Increment counter as we have new streams open
1267
- clearHttp2IdleTimeout(session)
1268
496
  ++session[kOpenStreams]
1269
497
 
1270
- if (headersTimeout) {
1271
- stream.setTimeout(headersTimeout)
1272
- }
1273
-
1274
- stream[kHTTP2Session] = session
1275
- stream.on('close', completeRequestStream)
1276
-
1277
- bindRequestToStream(request, stream, releaseRequestStream)
1278
- if (expectContinue) {
1279
- stream.once('continue', writeBodyH2)
1280
- }
1281
- // The handlers below either remove themselves on first invocation or
1282
- // become unreachable once the stream closes, so plain `on` avoids the
1283
- // per-listener `once` wrapper allocation.
1284
- stream.on('response', onResponse)
1285
- stream.on('headers', onInterimResponse)
1286
- stream.on('end', onEnd)
1287
- stream.on('error', onError)
1288
- stream.on('frameError', onFrameError)
1289
- stream.on('aborted', onAborted)
1290
- if (headersTimeout || bodyTimeout) {
1291
- stream.on('timeout', onTimeout)
1292
- }
1293
- stream.on('trailers', onTrailers)
1294
-
1295
- if (!expectContinue) {
1296
- writeBodyH2.call(stream)
1297
- }
1298
-
1299
- return true
1300
- }
1301
-
1302
- function removeRequestStreamListeners (stream) {
1303
- stream.off('error', noop)
1304
- stream.off('continue', writeBodyH2)
1305
- stream.off('response', onResponse)
1306
- stream.off('headers', onInterimResponse)
1307
- stream.off('end', onEnd)
1308
- stream.off('error', onError)
1309
- stream.off('frameError', onFrameError)
1310
- stream.off('aborted', onAborted)
1311
- stream.off('timeout', onTimeout)
1312
- stream.off('trailers', onTrailers)
1313
- stream.off('data', onData)
1314
- }
1315
-
1316
- function releaseRequestStream (stream) {
1317
- if (stream == null) {
1318
- return
1319
- }
1320
-
1321
- const state = stream[kRequestStreamState]
1322
- if (state == null) {
1323
- return
1324
- }
1325
-
1326
- const { request } = state
1327
-
1328
- if (request[kRequestStream] === stream) {
1329
- detachRequestFromStream(request)
1330
- }
1331
-
1332
- // A closed or destroyed stream cannot emit further events; leaving the
1333
- // listeners in place saves the removal scans (they are collected with
1334
- // the stream). All handlers bail out when the stream state is gone.
1335
- if (!stream.destroyed && !stream.closed) {
1336
- removeRequestStreamListeners(stream)
1337
- stream.once('error', noop)
1338
- }
1339
- }
1340
-
1341
- function onData (chunk) {
1342
- const stream = this
1343
- const state = stream[kRequestStreamState]
1344
-
1345
- if (state == null) {
1346
- return
1347
- }
1348
-
1349
- const { request, maxResponseSize, responseContentLength } = state
1350
-
1351
- if (request.aborted || request.completed) {
1352
- return
1353
- }
1354
-
1355
- if (responseContentLength != null && state.bytesRead + chunk.length > responseContentLength) {
1356
- state.abort(new ResponseContentLengthMismatchError())
1357
- return
1358
- }
1359
-
1360
- if (maxResponseSize > -1 && state.bytesRead + chunk.length > maxResponseSize) {
1361
- // Unlike HTTP/1.1, which destroys the socket because it cannot abandon one
1362
- // response without losing framing, resetting the offending stream leaves
1363
- // the session usable for its siblings.
1364
- state.abort(new ResponseExceededMaxSizeError())
1365
- return
1366
- }
1367
-
1368
- state.bytesRead += chunk.length
1369
-
1370
- if (request.onResponseData(chunk) === false) {
1371
- stream.pause()
1372
- }
1373
- }
1374
-
1375
- function onInterimResponse (headers) {
1376
- const stream = this
1377
- const state = stream[kRequestStreamState]
1378
-
1379
- if (state == null) {
1380
- return
1381
- }
1382
-
1383
- const { request } = state
1384
-
1385
- if (request.aborted || request.completed) {
1386
- return
1387
- }
1388
-
1389
- // node http2 emits 'headers' for interim (1xx) informational responses,
1390
- // while the final response arrives via 'response'. Forward these to the
1391
- // handler so that onInfo is invoked, matching the HTTP/1 behaviour and the
1392
- // documented onInfo contract.
1393
- const statusCode = headers[HTTP2_HEADER_STATUS]
1394
- delete headers[HTTP2_HEADER_STATUS]
1395
-
1396
- request.onResponseStart(Number(statusCode), headers, noop, '')
1397
- }
1398
-
1399
- function onResponse (headers) {
1400
- const stream = this
1401
- const state = stream[kRequestStreamState]
1402
-
1403
- if (state == null) {
1404
- return
1405
- }
1406
-
1407
- const { request } = state
1408
-
1409
- stream.off('response', onResponse)
1410
-
1411
- // Final response received while still awaiting 100 (Continue): the body won't
1412
- // be sent, so close our half or the stream stays open and never completes.
1413
- if (state.body != null && !state.bodySent && !stream.writableEnded) {
1414
- stream.removeListener('continue', writeBodyH2)
1415
- stream.end()
1416
- }
1417
-
1418
- const statusCode = Number(headers[HTTP2_HEADER_STATUS])
1419
- delete headers[HTTP2_HEADER_STATUS]
1420
- request.onResponseStarted()
1421
- state.responseReceived = true
1422
-
1423
- // A Content-Length in HEAD and 304 responses describes the selected
1424
- // representation rather than DATA on this stream. Successful CONNECT uses
1425
- // the upgrade path above; all other final responses use Content-Length as
1426
- // their DATA payload length.
1427
- if (request.method !== 'HEAD' && statusCode !== 304) {
1428
- const contentLength = headers[HTTP2_HEADER_CONTENT_LENGTH]
1429
- state.responseContentLength = contentLength == null ? null : Number(contentLength)
1430
- }
1431
-
1432
- if (state.headersTimeout || state.bodyTimeout) {
1433
- stream.setTimeout(state.bodyTimeout)
1434
- }
1435
-
1436
- // Due to the stream nature, it is possible we face a race condition
1437
- // where the stream has been assigned, but the request has been aborted
1438
- // or already completed and headers hasn't been received yet. A late
1439
- // 'response' delivered after completion would call request.onResponseStart
1440
- // post-completion, tripping its `assert(!this.completed)` (an uncatchable
1441
- // throw on the http2 event tick). Guard `completed` here as onEnd/onTrailers
1442
- // already do; best effort is to release the stream immediately as there's
1443
- // no value to keep it open.
1444
- if (request.aborted || request.completed) {
1445
- releaseRequestStream(stream)
1446
- return
1447
- }
1448
-
1449
- if (request.onResponseStart(statusCode, headers, stream.resume.bind(stream), '') === false) {
1450
- stream.pause()
1451
- }
1452
-
1453
- stream.on('data', onData)
1454
- }
1455
-
1456
- function onEnd () {
1457
- const stream = this
1458
- const state = stream[kRequestStreamState]
1459
-
1460
- if (state == null) {
1461
- return
1462
- }
1463
-
1464
- const { request } = state
498
+ stream.once('response', headers => {
499
+ const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
500
+ request.onResponseStarted()
501
+
502
+ // Due to the stream nature, it is possible we face a race condition
503
+ // where the stream has been assigned, but the request has been aborted
504
+ // the request remains in-flight and headers hasn't been received yet
505
+ // for those scenarios, best effort is to destroy the stream immediately
506
+ // as there's no value to keep it open.
507
+ if (request.aborted) {
508
+ const err = new RequestAbortedError()
509
+ util.errorRequest(client, request, err)
510
+ util.destroy(stream, err)
511
+ return
512
+ }
1465
513
 
1466
- stream.off('end', onEnd)
514
+ if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) {
515
+ stream.pause()
516
+ }
1467
517
 
1468
- // onTrailers (which may fire after 'end' on Windows) has already stored
1469
- // trailers on the state by now, so completing here still delivers them.
1470
- if (state.responseReceived) {
1471
- if (!request.aborted && !request.completed) {
1472
- if (state.responseContentLength != null && state.bytesRead !== state.responseContentLength) {
1473
- state.abort(new ResponseContentLengthMismatchError())
1474
- return
518
+ stream.on('data', (chunk) => {
519
+ if (request.onData(chunk) === false) {
520
+ stream.pause()
1475
521
  }
522
+ })
523
+ })
1476
524
 
1477
- state.pendingEnd = true
1478
-
1479
- // Complete on 'end': a blocked event loop can keep the stream's 'close'
1480
- // from firing, stranding its buffers until OOM. Idempotent, so a later
1481
- // 'close' no-ops.
1482
- completeRequestStream.call(stream)
525
+ stream.once('end', () => {
526
+ // When state is null, it means we haven't consumed body and the stream still do not have
527
+ // a state.
528
+ // Present specially when using pipeline or stream
529
+ if (stream.state?.state == null || stream.state.state < 6) {
530
+ request.onComplete([])
1483
531
  }
1484
- } else {
1485
- // Stream ended without receiving a response - this is an error
1486
- // (e.g., server destroyed the stream before sending headers)
1487
- state.abort(new InformationalError('HTTP/2: stream half-closed (remote)'), true)
1488
- }
1489
- }
1490
-
1491
- function retryRefusedStream (stream, state) {
1492
- const { client, request } = state
1493
-
1494
- if (
1495
- state.responseReceived ||
1496
- request.aborted ||
1497
- request.completed ||
1498
- request[kRefusedStreamRetry] ||
1499
- !canReplayRequest(request)
1500
- ) {
1501
- return false
1502
- }
1503
532
 
1504
- // RFC 9113 section 8.7 permits retrying REFUSED_STREAM, but says clients
1505
- // SHOULD NOT automatically retry the same request more than once.
1506
- request[kRefusedStreamRetry] = true
533
+ if (session[kOpenStreams] === 0) {
534
+ // Stream is closed or half-closed-remote (6), decrement counter and cleanup
535
+ // It does not have sense to continue working with the stream as we do not
536
+ // have yet RST_STREAM support on client-side
1507
537
 
1508
- // Detach the failed attempt before moving the request back to the pending
1509
- // queue. The peer only reset this stream, so the HTTP/2 session remains
1510
- // usable for the retry. Severing also drops the 'close' listener, so the
1511
- // abandoned stream cannot later complete the retried request.
1512
- detachRequestStreamForClose(request)
1513
- state.stream = null
1514
- state.requestFinalized = true
1515
-
1516
- completeRequest(client, request)
1517
- client[kQueue].splice(client[kPendingIdx], 0, request)
1518
- client[kResume]()
1519
-
1520
- return true
1521
- }
1522
-
1523
- function onError (err) {
1524
- const stream = this
1525
- const state = stream[kRequestStreamState]
1526
-
1527
- if (state == null) {
1528
- return
1529
- }
1530
-
1531
- stream.off('error', onError)
1532
-
1533
- // Node's HTTP/2 implementation can turn an incomplete Content-Length body
1534
- // into a protocol stream error instead of emitting 'end'. Prefer the
1535
- // content-length mismatch error when the received byte count proves it.
1536
- if (state.responseContentLength != null && state.bytesRead !== state.responseContentLength) {
1537
- err = new ResponseContentLengthMismatchError()
1538
- }
1539
-
1540
- if (typeof stream.rstCode === 'number' && stream.rstCode !== NGHTTP2_NO_ERROR) {
1541
- err.http2ErrorCode = stream.rstCode
1542
- }
1543
-
1544
- if (
1545
- stream.rstCode === NGHTTP2_REFUSED_STREAM &&
1546
- retryRefusedStream(stream, state)
1547
- ) {
1548
- return
1549
- }
1550
-
1551
- state.abort(err)
1552
- }
1553
-
1554
- function onFrameError (type, code) {
1555
- const stream = this
1556
- const state = stream[kRequestStreamState]
1557
-
1558
- if (state == null) {
1559
- return
1560
- }
1561
-
1562
- stream.off('frameError', onFrameError)
1563
- state.abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
1564
- }
1565
-
1566
- function onAborted () {
1567
- this.off('data', onData)
1568
- }
1569
-
1570
- function onTimeout () {
1571
- const stream = this
1572
- const state = stream[kRequestStreamState]
538
+ session.unref()
539
+ }
1573
540
 
1574
- if (state == null) {
1575
- return
1576
- }
541
+ abort(new InformationalError('HTTP/2: stream half-closed (remote)'))
542
+ client[kQueue][client[kRunningIdx]++] = null
543
+ client[kPendingIdx] = client[kRunningIdx]
544
+ client[kResume]()
545
+ })
1577
546
 
1578
- // Remove self so timeout doesn't fire again after we handle it
1579
- stream.off('timeout', onTimeout)
547
+ stream.once('close', () => {
548
+ session[kOpenStreams] -= 1
549
+ if (session[kOpenStreams] === 0) {
550
+ session.unref()
551
+ }
552
+ })
1580
553
 
1581
- const err = state.responseReceived
1582
- ? new BodyTimeoutError(`HTTP/2: "stream timeout after ${state.bodyTimeout}"`)
1583
- : new HeadersTimeoutError(`HTTP/2: "headers timeout after ${state.headersTimeout}"`)
1584
- state.abort(err)
1585
- }
554
+ stream.once('error', function (err) {
555
+ abort(err)
556
+ })
1586
557
 
1587
- function onTrailers (trailers) {
1588
- const stream = this
1589
- const state = stream[kRequestStreamState]
558
+ stream.once('frameError', (type, code) => {
559
+ abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
560
+ })
1590
561
 
1591
- if (state == null) {
1592
- return
1593
- }
562
+ // stream.on('aborted', () => {
563
+ // // TODO(HTTP/2): Support aborted
564
+ // })
1594
565
 
1595
- const { request } = state
566
+ // stream.on('timeout', () => {
567
+ // // TODO(HTTP/2): Support timeout
568
+ // })
1596
569
 
1597
- stream.off('trailers', onTrailers)
1598
- stream.off('data', onData)
570
+ // stream.on('push', headers => {
571
+ // // TODO(HTTP/2): Support push
572
+ // })
1599
573
 
1600
- if (request.aborted || request.completed) {
1601
- return
1602
- }
574
+ // stream.on('trailers', headers => {
575
+ // // TODO(HTTP/2): Support trailers
576
+ // })
1603
577
 
1604
- // Store trailers for completeRequestStream to use when completing
1605
- state.trailers = trailers
1606
- }
578
+ return true
1607
579
 
1608
- function writeBodyH2 () {
1609
- const stream = this
1610
- const state = stream[kRequestStreamState]
1611
- state.bodySent = true
1612
- const { abort, body, client, contentLength, expectsPayload, request } = state
1613
-
1614
- if (!body || contentLength === 0) {
1615
- writeBuffer(
1616
- abort,
1617
- stream,
1618
- null,
1619
- client,
1620
- request,
1621
- client[kSocket],
1622
- contentLength,
1623
- expectsPayload
1624
- )
1625
- } else if (util.isBuffer(body)) {
1626
- writeBuffer(
1627
- abort,
1628
- stream,
1629
- body,
1630
- client,
1631
- request,
1632
- client[kSocket],
1633
- contentLength,
1634
- expectsPayload
1635
- )
1636
- } else if (util.isBlobLike(body)) {
1637
- if (typeof body.stream === 'function') {
1638
- writeIterable(
580
+ function writeBodyH2 () {
581
+ /* istanbul ignore else: assertion */
582
+ if (!body || contentLength === 0) {
583
+ writeBuffer(
1639
584
  abort,
1640
585
  stream,
1641
- body.stream(),
586
+ null,
1642
587
  client,
1643
588
  request,
1644
589
  client[kSocket],
1645
590
  contentLength,
1646
591
  expectsPayload
1647
592
  )
1648
- } else {
1649
- writeBlob(
593
+ } else if (util.isBuffer(body)) {
594
+ writeBuffer(
595
+ abort,
596
+ stream,
597
+ body,
598
+ client,
599
+ request,
600
+ client[kSocket],
601
+ contentLength,
602
+ expectsPayload
603
+ )
604
+ } else if (util.isBlobLike(body)) {
605
+ if (typeof body.stream === 'function') {
606
+ writeIterable(
607
+ abort,
608
+ stream,
609
+ body.stream(),
610
+ client,
611
+ request,
612
+ client[kSocket],
613
+ contentLength,
614
+ expectsPayload
615
+ )
616
+ } else {
617
+ writeBlob(
618
+ abort,
619
+ stream,
620
+ body,
621
+ client,
622
+ request,
623
+ client[kSocket],
624
+ contentLength,
625
+ expectsPayload
626
+ )
627
+ }
628
+ } else if (util.isStream(body)) {
629
+ writeStream(
630
+ abort,
631
+ client[kSocket],
632
+ expectsPayload,
633
+ stream,
634
+ body,
635
+ client,
636
+ request,
637
+ contentLength
638
+ )
639
+ } else if (util.isIterable(body)) {
640
+ writeIterable(
1650
641
  abort,
1651
642
  stream,
1652
643
  body,
@@ -1656,31 +647,9 @@ function writeBodyH2 () {
1656
647
  contentLength,
1657
648
  expectsPayload
1658
649
  )
650
+ } else {
651
+ assert(false)
1659
652
  }
1660
- } else if (util.isStream(body)) {
1661
- writeStream(
1662
- abort,
1663
- client[kSocket],
1664
- expectsPayload,
1665
- stream,
1666
- body,
1667
- client,
1668
- request,
1669
- contentLength
1670
- )
1671
- } else if (util.isIterable(body)) {
1672
- writeIterable(
1673
- abort,
1674
- stream,
1675
- body,
1676
- client,
1677
- request,
1678
- client[kSocket],
1679
- contentLength,
1680
- expectsPayload
1681
- )
1682
- } else {
1683
- assert(false)
1684
653
  }
1685
654
  }
1686
655
 
@@ -1739,6 +708,8 @@ function writeStream (abort, socket, expectsPayload, h2stream, body, client, req
1739
708
  }
1740
709
 
1741
710
  async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) {
711
+ assert(contentLength === body.size, 'blob body must have content length')
712
+
1742
713
  try {
1743
714
  if (contentLength != null && contentLength !== body.size) {
1744
715
  throw new RequestContentLengthMismatchError()