@openclaw/slack 2026.9.5 → 2026.9.7

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 (648) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{account-inspect-B86OaUEt.mjs → account-inspect-DWBXpER6.mjs} +1 -1
  3. package/dist/.setup/{accounts-C1FspRF-.mjs → accounts-D_N9IqNA.mjs} +33 -10
  4. package/dist/.setup/{action-runtime-Aa-h24Fq.mjs → action-runtime-DfWvuiZd.mjs} +46 -65
  5. package/dist/.setup/action-runtime.runtime-Ck4bAWOX.mjs +2 -0
  6. package/dist/.setup/{actions-BvGUGk3w.mjs → actions-Df0CzcDl.mjs} +148 -204
  7. package/dist/.setup/{approval-handler.runtime-BcZNF-VP.mjs → approval-handler.runtime-Ed6Sw5VK.mjs} +37 -47
  8. package/dist/.setup/{approval-message-updates-Cy1cxfBn.mjs → approval-message-updates-BadvtA7R.mjs} +1 -2
  9. package/dist/.setup/{channel-DrBm0NFw.mjs → channel-C7bgPSTE.mjs} +192 -280
  10. package/dist/.setup/channel-meta-C443t-lI.mjs +27 -0
  11. package/dist/.setup/{channel-type-osC0XOES.mjs → channel-type-ClOttrZ5.mjs} +13 -21
  12. package/dist/.setup/{channel.setup-BSY5hzVz.mjs → channel.setup-Dh2jzAjN.mjs} +35 -42
  13. package/dist/.setup/{config-schema-DrY3S7Ee.mjs → config-schema-BZCxmHKG.mjs} +32 -21
  14. package/dist/.setup/{directory-config-CTs7YyuU.mjs → directory-config-BOUWH3hR.mjs} +7 -10
  15. package/dist/.setup/{directory-live-Btq0063Q.mjs → directory-live-B2O4B_Ho.mjs} +9 -21
  16. package/dist/.setup/doctor-contract-CRN1Z_c7.mjs +342 -0
  17. package/dist/.setup/{message-tool-api-DRnDCVdY.mjs → message-tool-api-Cu4lwlGy.mjs} +34 -48
  18. package/dist/.setup/{provider-w36VTgZ3.mjs → monitor-BPVfkumU.mjs} +2191 -2704
  19. package/dist/.setup/{outbound-adapter-K3Ek1iSR.mjs → outbound-adapter-Bv48XUjq.mjs} +10 -21
  20. package/dist/.setup/{pipeline.runtime-BZqGcbfi.mjs → pipeline.runtime-B1H63Frf.mjs} +901 -892
  21. package/dist/.setup/{plugin-routes-C3X0eVaK.mjs → plugin-routes-B8tooDLj.mjs} +1 -1
  22. package/dist/.setup/{policy-Db_QWCZZ.mjs → policy-D-jfM174.mjs} +5 -5
  23. package/dist/.setup/{probe-64C6k3_Q.mjs → probe-B2Y9qc_z.mjs} +101 -39
  24. package/dist/.setup/{registry-bbjH7IHX.mjs → registry-CIbMfuf8.mjs} +6 -2
  25. package/dist/.setup/{relay-source-CDqY76Vp.mjs → relay-source-BpKdjsll.mjs} +10 -12
  26. package/dist/.setup/{replies-CWFhjS9S.mjs → replies-BAnUtr2f.mjs} +16 -76
  27. package/dist/.setup/{reply-blocks-9uCeAJts.mjs → reply-blocks-SE1kTE3I.mjs} +27 -154
  28. package/dist/.setup/{resolve-channels-x8fX1SEt.mjs → resolve-channels-XXBn8UU_.mjs} +4 -5
  29. package/dist/.setup/{resolve-users-B8BpBnH2.mjs → resolve-users-DW0ngD03.mjs} +20 -22
  30. package/dist/.setup/{scopes-CJ-6l4v4.mjs → scopes-CasuDvaa.mjs} +6 -17
  31. package/dist/.setup/{secret-contract-DxmvbxBF.mjs → secret-contract-BaZcu6P_.mjs} +15 -20
  32. package/dist/.setup/{secret-contract-api-D9UfYujm.mjs → secret-contract-api-Dp6290Vg.mjs} +1 -1
  33. package/dist/.setup/{security-audit-BypHqcq5.mjs → security-audit-BqDc-6VL.mjs} +1 -1
  34. package/dist/.setup/{send-6GCb3lBP.mjs → send-BOVLQi3n.mjs} +102 -199
  35. package/dist/.setup/{session-status-BhG6pdiH.mjs → session-status-DscajIsd.mjs} +323 -250
  36. package/dist/.setup/{setup-plugin-api-DtCEByQB.mjs → setup-plugin-api-DTtbTKNk.mjs} +1 -1
  37. package/dist/.setup/{setup-surface-DsE0hsYY.mjs → setup-surface-Dn7QgWRE.mjs} +24 -56
  38. package/dist/.setup/{shared-BNmqCPgQ.mjs → shared-qau-uDGl.mjs} +30 -56
  39. package/dist/.setup/{slash-dispatch.runtime-Io4ASZsY.mjs → slash-dispatch.runtime--AEzLVBF.mjs} +1 -1
  40. package/dist/.setup/{streaming-compat-B-e0mqM0.mjs → streaming-compat-C5Wut626.mjs} +31 -8
  41. package/dist/.setup/{target-parsing-DEsPjngB.mjs → target-parsing-FFE26kOV.mjs} +1 -7
  42. package/dist/.setup/{targets-Cku2KCvg.mjs → targets-C6LZQL1Q.mjs} +1 -1
  43. package/dist/.setup/{thread-ts-CukseRVL.mjs → thread-ts-Cvt7WD6B.mjs} +0 -1
  44. package/dist/account-inspect-api.js +1 -1
  45. package/dist/api.js +18 -17
  46. package/dist/channel-config-api.js +1 -1
  47. package/dist/channel-plugin-api.js +1 -1
  48. package/dist/directory-contract-api.js +1 -1
  49. package/dist/doctor-contract-api.js +1 -1
  50. package/dist/http-routes-api.js +1 -1
  51. package/dist/index.js +1 -1
  52. package/dist/message-tool-api.js +1 -1
  53. package/dist/runtime-api.js +11 -12
  54. package/dist/secret-contract-api.js +1 -1
  55. package/dist/security-contract-api.js +1 -1
  56. package/dist/setup-entry.js +2 -2
  57. package/dist/setup-plugin-api.js +1 -1
  58. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
  59. package/node_modules/@slack/bolt/node_modules/@types/node/child_process.d.ts +1 -1
  60. package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +20 -8
  61. package/node_modules/@slack/bolt/node_modules/@types/node/ffi.d.ts +14 -0
  62. package/node_modules/@slack/bolt/node_modules/@types/node/http2.d.ts +3 -2
  63. package/node_modules/@slack/bolt/node_modules/@types/node/net.d.ts +16 -4
  64. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
  65. package/node_modules/@slack/bolt/node_modules/@types/node/process.d.ts +1 -0
  66. package/node_modules/@slack/bolt/node_modules/@types/node/quic.d.ts +39 -1
  67. package/node_modules/@slack/bolt/node_modules/@types/node/stream/iter.d.ts +9 -12
  68. package/node_modules/@slack/bolt/node_modules/@types/node/test/reporters.d.ts +1 -0
  69. package/node_modules/@slack/bolt/node_modules/@types/node/test.d.ts +72 -0
  70. package/node_modules/@slack/bolt/node_modules/@types/node/tls.d.ts +14 -10
  71. package/node_modules/@slack/bolt/node_modules/@types/node/vm.d.ts +2 -1
  72. package/node_modules/@slack/bolt/node_modules/@types/node/web-globals/streams.d.ts +4 -0
  73. package/node_modules/@slack/bolt/node_modules/@types/node/worker_threads.d.ts +4 -1
  74. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
  75. package/node_modules/@slack/web-api/node_modules/@types/node/child_process.d.ts +1 -1
  76. package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +20 -8
  77. package/node_modules/@slack/web-api/node_modules/@types/node/ffi.d.ts +14 -0
  78. package/node_modules/@slack/web-api/node_modules/@types/node/http2.d.ts +3 -2
  79. package/node_modules/@slack/web-api/node_modules/@types/node/net.d.ts +16 -4
  80. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
  81. package/node_modules/@slack/web-api/node_modules/@types/node/process.d.ts +1 -0
  82. package/node_modules/@slack/web-api/node_modules/@types/node/quic.d.ts +39 -1
  83. package/node_modules/@slack/web-api/node_modules/@types/node/stream/iter.d.ts +9 -12
  84. package/node_modules/@slack/web-api/node_modules/@types/node/test/reporters.d.ts +1 -0
  85. package/node_modules/@slack/web-api/node_modules/@types/node/test.d.ts +72 -0
  86. package/node_modules/@slack/web-api/node_modules/@types/node/tls.d.ts +14 -10
  87. package/node_modules/@slack/web-api/node_modules/@types/node/vm.d.ts +2 -1
  88. package/node_modules/@slack/web-api/node_modules/@types/node/web-globals/streams.d.ts +4 -0
  89. package/node_modules/@slack/web-api/node_modules/@types/node/worker_threads.d.ts +4 -1
  90. package/node_modules/get-east-asian-width/index.js +8 -3
  91. package/node_modules/get-east-asian-width/lookup-data.js +1 -1
  92. package/node_modules/get-east-asian-width/lookup.js +4 -4
  93. package/node_modules/get-east-asian-width/package.json +1 -1
  94. package/node_modules/typebox/build/compile/code.mjs +1 -2
  95. package/node_modules/typebox/build/compile/validator.mjs +5 -1
  96. package/node_modules/typebox/build/format/iri.mjs +16 -9
  97. package/node_modules/typebox/build/guard/emit.mjs +2 -2
  98. package/node_modules/typebox/build/guard/guard.d.mts +7 -5
  99. package/node_modules/typebox/build/guard/guard.mjs +14 -9
  100. package/node_modules/typebox/build/guard/index.mjs +6 -0
  101. package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
  102. package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
  103. package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
  104. package/node_modules/typebox/build/schema/build.mjs +2 -3
  105. package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
  106. package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
  107. package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
  108. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
  109. package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
  110. package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
  111. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
  112. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
  113. package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
  114. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
  115. package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
  116. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
  117. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
  118. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
  119. package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
  120. package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
  121. package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
  122. package/node_modules/typebox/build/schema/parse.mjs +3 -0
  123. package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
  124. package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
  125. package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
  126. package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
  127. package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
  128. package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
  129. package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
  130. package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
  131. package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
  132. package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
  133. package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
  134. package/node_modules/typebox/package.json +1 -1
  135. package/node_modules/typebox/readme.md +3 -1
  136. package/node_modules/undici/README.md +81 -25
  137. package/node_modules/undici/docs/docs/api/Agent.md +249 -42
  138. package/node_modules/undici/docs/docs/api/BalancedPool.md +246 -48
  139. package/node_modules/undici/docs/docs/api/CacheStorage.md +171 -13
  140. package/node_modules/undici/docs/docs/api/CacheStore.md +294 -98
  141. package/node_modules/undici/docs/docs/api/Client.md +407 -162
  142. package/node_modules/undici/docs/docs/api/ClientStats.md +80 -14
  143. package/node_modules/undici/docs/docs/api/Connector.md +118 -35
  144. package/node_modules/undici/docs/docs/api/ContentType.md +65 -25
  145. package/node_modules/undici/docs/docs/api/Cookies.md +122 -71
  146. package/node_modules/undici/docs/docs/api/Debug.md +34 -18
  147. package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +364 -164
  148. package/node_modules/undici/docs/docs/api/Dispatcher.md +490 -1055
  149. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +105 -93
  150. package/node_modules/undici/docs/docs/api/Errors.md +503 -28
  151. package/node_modules/undici/docs/docs/api/EventSource.md +326 -13
  152. package/node_modules/undici/docs/docs/api/Fetch.md +681 -30
  153. package/node_modules/undici/docs/docs/api/GlobalInstallation.md +78 -96
  154. package/node_modules/undici/docs/docs/api/H2CClient.md +298 -176
  155. package/node_modules/undici/docs/docs/api/Interceptors.md +418 -0
  156. package/node_modules/undici/docs/docs/api/MockAgent.md +333 -314
  157. package/node_modules/undici/docs/docs/api/MockCallHistory.md +272 -98
  158. package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +189 -26
  159. package/node_modules/undici/docs/docs/api/MockClient.md +151 -33
  160. package/node_modules/undici/docs/docs/api/MockErrors.md +56 -5
  161. package/node_modules/undici/docs/docs/api/MockPool.md +321 -258
  162. package/node_modules/undici/docs/docs/api/Pool.md +236 -41
  163. package/node_modules/undici/docs/docs/api/PoolStats.md +119 -13
  164. package/node_modules/undici/docs/docs/api/ProxyAgent.md +179 -160
  165. package/node_modules/undici/docs/docs/api/RedirectHandler.md +238 -55
  166. package/node_modules/undici/docs/docs/api/RetryAgent.md +113 -27
  167. package/node_modules/undici/docs/docs/api/RetryHandler.md +161 -79
  168. package/node_modules/undici/docs/docs/api/RoundRobinPool.md +166 -72
  169. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +262 -517
  170. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +177 -196
  171. package/node_modules/undici/docs/docs/api/Util.md +68 -11
  172. package/node_modules/undici/docs/docs/api/WebSocket.md +475 -80
  173. package/node_modules/undici/docs/docs/api/api-lifecycle.md +100 -32
  174. package/node_modules/undici/docs/docs/best-practices/client-certificate.md +2 -0
  175. package/node_modules/undici/docs/docs/best-practices/crawling.md +3 -1
  176. package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +233 -0
  177. package/node_modules/undici/docs/docs/best-practices/mocking-request.md +9 -7
  178. package/node_modules/undici/docs/docs/best-practices/proxy.md +3 -1
  179. package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +10 -8
  180. package/node_modules/undici/docs/docs/best-practices/writing-tests.md +2 -0
  181. package/node_modules/undici/docs/docs/getting-started.md +281 -0
  182. package/node_modules/undici/docs/docs/index.md +784 -0
  183. package/node_modules/undici/docs/docs/site.json +125 -0
  184. package/node_modules/undici/docs/docs/type-map.json +79 -0
  185. package/node_modules/undici/index.js +4 -2
  186. package/node_modules/undici/lib/api/api-connect.js +13 -11
  187. package/node_modules/undici/lib/api/api-pipeline.js +26 -13
  188. package/node_modules/undici/lib/api/api-request.js +51 -21
  189. package/node_modules/undici/lib/api/api-stream.js +81 -20
  190. package/node_modules/undici/lib/api/api-upgrade.js +21 -11
  191. package/node_modules/undici/lib/api/readable.js +45 -9
  192. package/node_modules/undici/lib/cache/memory-cache-store.js +3 -3
  193. package/node_modules/undici/lib/cache/sqlite-cache-store.js +3 -1
  194. package/node_modules/undici/lib/core/connect.js +46 -7
  195. package/node_modules/undici/lib/core/constants.js +1 -24
  196. package/node_modules/undici/lib/core/errors.js +22 -2
  197. package/node_modules/undici/lib/core/request.js +100 -18
  198. package/node_modules/undici/lib/core/symbols.js +4 -0
  199. package/node_modules/undici/lib/core/util.js +105 -48
  200. package/node_modules/undici/lib/dispatcher/agent.js +51 -32
  201. package/node_modules/undici/lib/dispatcher/balanced-pool.js +23 -27
  202. package/node_modules/undici/lib/dispatcher/client-h1.js +86 -24
  203. package/node_modules/undici/lib/dispatcher/client-h2.js +1091 -361
  204. package/node_modules/undici/lib/dispatcher/client.js +109 -36
  205. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +19 -6
  206. package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -5
  207. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +110 -0
  208. package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +37 -8
  209. package/node_modules/undici/lib/dispatcher/h2c-client.js +4 -4
  210. package/node_modules/undici/lib/dispatcher/pool-base.js +28 -10
  211. package/node_modules/undici/lib/dispatcher/pool.js +30 -5
  212. package/node_modules/undici/lib/dispatcher/proxy-agent.js +95 -19
  213. package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
  214. package/node_modules/undici/lib/dispatcher/round-robin-pool.js +32 -10
  215. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +153 -63
  216. package/node_modules/undici/lib/global.js +37 -14
  217. package/node_modules/undici/lib/handler/cache-handler.js +49 -7
  218. package/node_modules/undici/lib/handler/cache-revalidation-handler.js +10 -0
  219. package/node_modules/undici/lib/handler/decorator-handler.js +8 -3
  220. package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
  221. package/node_modules/undici/lib/handler/redirect-handler.js +66 -66
  222. package/node_modules/undici/lib/handler/retry-handler.js +191 -50
  223. package/node_modules/undici/lib/interceptor/cache.js +75 -25
  224. package/node_modules/undici/lib/interceptor/decompress.js +5 -2
  225. package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
  226. package/node_modules/undici/lib/interceptor/dns.js +12 -1
  227. package/node_modules/undici/lib/interceptor/redirect.js +3 -3
  228. package/node_modules/undici/lib/llhttp/llhttp-wasm.js +1 -1
  229. package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +1 -1
  230. package/node_modules/undici/lib/mock/mock-agent.js +21 -9
  231. package/node_modules/undici/lib/mock/mock-call-history.js +1 -1
  232. package/node_modules/undici/lib/mock/mock-interceptor.js +25 -7
  233. package/node_modules/undici/lib/mock/mock-utils.js +281 -47
  234. package/node_modules/undici/lib/mock/snapshot-agent.js +25 -7
  235. package/node_modules/undici/lib/mock/snapshot-recorder.js +38 -3
  236. package/node_modules/undici/lib/util/cache.js +92 -10
  237. package/node_modules/undici/lib/util/runtime-features.js +3 -34
  238. package/node_modules/undici/lib/web/cache/cache.js +6 -8
  239. package/node_modules/undici/lib/web/cookies/parse.js +150 -146
  240. package/node_modules/undici/lib/web/cookies/util.js +1 -1
  241. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
  242. package/node_modules/undici/lib/web/eventsource/eventsource.js +20 -21
  243. package/node_modules/undici/lib/web/eventsource/util.js +32 -1
  244. package/node_modules/undici/lib/web/fetch/body.js +48 -10
  245. package/node_modules/undici/lib/web/fetch/constants.js +1 -1
  246. package/node_modules/undici/lib/web/fetch/formdata.js +21 -2
  247. package/node_modules/undici/lib/web/fetch/index.js +242 -223
  248. package/node_modules/undici/lib/web/fetch/request.js +35 -6
  249. package/node_modules/undici/lib/web/fetch/response.js +1 -3
  250. package/node_modules/undici/lib/web/fetch/util.js +10 -2
  251. package/node_modules/undici/lib/web/webidl/index.js +5 -7
  252. package/node_modules/undici/lib/web/websocket/frame.js +1 -7
  253. package/node_modules/undici/lib/web/websocket/receiver.js +1 -1
  254. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +10 -10
  255. package/node_modules/undici/lib/web/websocket/websocket.js +25 -3
  256. package/node_modules/undici/package.json +10 -10
  257. package/node_modules/undici/types/agent.d.ts +0 -2
  258. package/node_modules/undici/types/client.d.ts +69 -24
  259. package/node_modules/undici/types/connector.d.ts +1 -0
  260. package/node_modules/undici/types/cookies.d.ts +1 -1
  261. package/node_modules/undici/types/dispatcher.d.ts +8 -30
  262. package/node_modules/undici/types/dispatcher1-wrapper.d.ts +7 -0
  263. package/node_modules/undici/types/errors.d.ts +10 -0
  264. package/node_modules/undici/types/fetch.d.ts +5 -1
  265. package/node_modules/undici/types/formdata.d.ts +0 -6
  266. package/node_modules/undici/types/h2c-client.d.ts +6 -6
  267. package/node_modules/undici/types/handlers.d.ts +2 -0
  268. package/node_modules/undici/types/header.d.ts +5 -0
  269. package/node_modules/undici/types/index.d.ts +3 -1
  270. package/node_modules/undici/types/interceptors.d.ts +1 -1
  271. package/node_modules/undici/types/mock-agent.d.ts +11 -10
  272. package/node_modules/undici/types/mock-interceptor.d.ts +5 -1
  273. package/node_modules/undici/types/pool.d.ts +0 -2
  274. package/node_modules/undici/types/proxy-agent.d.ts +9 -2
  275. package/node_modules/undici/types/round-robin-pool.d.ts +0 -2
  276. package/node_modules/undici/types/snapshot-agent.d.ts +4 -0
  277. package/node_modules/undici/types/socks5-proxy-agent.d.ts +4 -2
  278. package/node_modules/undici/types/webidl.d.ts +0 -1
  279. package/node_modules/zod/README.md +2 -2
  280. package/node_modules/zod/compile.cjs +19 -0
  281. package/node_modules/zod/index.cjs +19 -0
  282. package/node_modules/zod/locales/index.cjs +19 -0
  283. package/node_modules/zod/mini/index.cjs +19 -0
  284. package/node_modules/zod/package.json +8 -7
  285. package/node_modules/zod/src/v3/helpers/errorUtil.ts +1 -1
  286. package/node_modules/zod/src/v4/classic/external.ts +2 -0
  287. package/node_modules/zod/src/v4/classic/from-json-schema.ts +248 -25
  288. package/node_modules/zod/src/v4/classic/schemas.ts +243 -168
  289. package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +60 -9
  290. package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +6 -0
  291. package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +2 -2
  292. package/node_modules/zod/src/v4/classic/tests/cyclic-data.test.ts +265 -0
  293. package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +112 -6
  294. package/node_modules/zod/src/v4/classic/tests/enum.test.ts +9 -0
  295. package/node_modules/zod/src/v4/classic/tests/error.test.ts +130 -1
  296. package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +157 -0
  297. package/node_modules/zod/src/v4/classic/tests/iban.test.ts +81 -0
  298. package/node_modules/zod/src/v4/classic/tests/instance-footprint.test.ts +40 -2
  299. package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +27 -7
  300. package/node_modules/zod/src/v4/classic/tests/issue-schema.test.ts +88 -56
  301. package/node_modules/zod/src/v4/classic/tests/number.test.ts +39 -0
  302. package/node_modules/zod/src/v4/classic/tests/object.test.ts +56 -0
  303. package/node_modules/zod/src/v4/classic/tests/optin-ladder.test.ts +3 -2
  304. package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +70 -0
  305. package/node_modules/zod/src/v4/classic/tests/properties.test.ts +141 -0
  306. package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +46 -1
  307. package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +19 -0
  308. package/node_modules/zod/src/v4/classic/tests/string.test.ts +95 -1
  309. package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +33 -1
  310. package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +234 -38
  311. package/node_modules/zod/src/v4/classic/tests/validate.test.ts +569 -0
  312. package/node_modules/zod/src/v4/core/api.ts +44 -28
  313. package/node_modules/zod/src/v4/core/checks.ts +62 -102
  314. package/node_modules/zod/src/v4/core/compile.ts +218 -93
  315. package/node_modules/zod/src/v4/core/core.ts +1 -3
  316. package/node_modules/zod/src/v4/core/doc.ts +6 -2
  317. package/node_modules/zod/src/v4/core/errors.ts +3 -6
  318. package/node_modules/zod/src/v4/core/json-schema-generator.ts +2 -2
  319. package/node_modules/zod/src/v4/core/json-schema-processors.ts +185 -81
  320. package/node_modules/zod/src/v4/core/memoizer.ts +75 -28
  321. package/node_modules/zod/src/v4/core/parse.ts +37 -16
  322. package/node_modules/zod/src/v4/core/regexes.ts +14 -4
  323. package/node_modules/zod/src/v4/core/schemas.ts +296 -132
  324. package/node_modules/zod/src/v4/core/tests/cached.test.ts +54 -0
  325. package/node_modules/zod/src/v4/core/tests/compile-differential.test.ts +35 -0
  326. package/node_modules/zod/src/v4/core/tests/compile-generative.test.ts +445 -0
  327. package/node_modules/zod/src/v4/core/tests/compile.test.ts +399 -2
  328. package/node_modules/zod/src/v4/core/tests/email-regex.test.ts +140 -0
  329. package/node_modules/zod/src/v4/core/tests/locales/tg.test.ts +85 -0
  330. package/node_modules/zod/src/v4/core/tests/polyfill-collision.test.ts +46 -0
  331. package/node_modules/zod/src/v4/core/tests/url-no-canparse.test.ts +118 -16
  332. package/node_modules/zod/src/v4/core/to-json-schema.ts +9 -7
  333. package/node_modules/zod/src/v4/core/util.ts +218 -147
  334. package/node_modules/zod/src/v4/core/versions.ts +2 -2
  335. package/node_modules/zod/src/v4/locales/ar.ts +2 -0
  336. package/node_modules/zod/src/v4/locales/az.ts +2 -0
  337. package/node_modules/zod/src/v4/locales/be.ts +2 -0
  338. package/node_modules/zod/src/v4/locales/bg.ts +2 -0
  339. package/node_modules/zod/src/v4/locales/bn.ts +2 -0
  340. package/node_modules/zod/src/v4/locales/ca.ts +2 -0
  341. package/node_modules/zod/src/v4/locales/ckb.ts +2 -0
  342. package/node_modules/zod/src/v4/locales/cs.ts +2 -0
  343. package/node_modules/zod/src/v4/locales/da.ts +2 -0
  344. package/node_modules/zod/src/v4/locales/de.ts +2 -0
  345. package/node_modules/zod/src/v4/locales/el.ts +2 -0
  346. package/node_modules/zod/src/v4/locales/en.ts +2 -0
  347. package/node_modules/zod/src/v4/locales/eo.ts +2 -0
  348. package/node_modules/zod/src/v4/locales/es.ts +2 -0
  349. package/node_modules/zod/src/v4/locales/fa.ts +2 -0
  350. package/node_modules/zod/src/v4/locales/fi.ts +2 -0
  351. package/node_modules/zod/src/v4/locales/fr-CA.ts +2 -0
  352. package/node_modules/zod/src/v4/locales/fr.ts +2 -0
  353. package/node_modules/zod/src/v4/locales/gu.ts +2 -0
  354. package/node_modules/zod/src/v4/locales/he.ts +2 -0
  355. package/node_modules/zod/src/v4/locales/hi.ts +2 -0
  356. package/node_modules/zod/src/v4/locales/hr.ts +2 -0
  357. package/node_modules/zod/src/v4/locales/hu.ts +2 -0
  358. package/node_modules/zod/src/v4/locales/hy.ts +2 -0
  359. package/node_modules/zod/src/v4/locales/id.ts +2 -0
  360. package/node_modules/zod/src/v4/locales/index.ts +1 -0
  361. package/node_modules/zod/src/v4/locales/is.ts +2 -0
  362. package/node_modules/zod/src/v4/locales/it.ts +2 -0
  363. package/node_modules/zod/src/v4/locales/ja.ts +2 -0
  364. package/node_modules/zod/src/v4/locales/ka.ts +2 -0
  365. package/node_modules/zod/src/v4/locales/km.ts +2 -0
  366. package/node_modules/zod/src/v4/locales/kn.ts +2 -0
  367. package/node_modules/zod/src/v4/locales/ko.ts +2 -0
  368. package/node_modules/zod/src/v4/locales/lt.ts +2 -0
  369. package/node_modules/zod/src/v4/locales/mk.ts +2 -0
  370. package/node_modules/zod/src/v4/locales/ms.ts +2 -0
  371. package/node_modules/zod/src/v4/locales/ne.ts +2 -0
  372. package/node_modules/zod/src/v4/locales/nl.ts +2 -0
  373. package/node_modules/zod/src/v4/locales/nn.ts +2 -0
  374. package/node_modules/zod/src/v4/locales/no.ts +2 -0
  375. package/node_modules/zod/src/v4/locales/ota.ts +2 -0
  376. package/node_modules/zod/src/v4/locales/pl.ts +2 -0
  377. package/node_modules/zod/src/v4/locales/ps.ts +2 -0
  378. package/node_modules/zod/src/v4/locales/pt-BR.ts +2 -0
  379. package/node_modules/zod/src/v4/locales/pt.ts +2 -0
  380. package/node_modules/zod/src/v4/locales/ro.ts +2 -0
  381. package/node_modules/zod/src/v4/locales/ru.ts +2 -0
  382. package/node_modules/zod/src/v4/locales/sk.ts +2 -0
  383. package/node_modules/zod/src/v4/locales/sl.ts +2 -0
  384. package/node_modules/zod/src/v4/locales/sv.ts +2 -0
  385. package/node_modules/zod/src/v4/locales/ta.ts +2 -0
  386. package/node_modules/zod/src/v4/locales/tg.ts +135 -0
  387. package/node_modules/zod/src/v4/locales/th.ts +2 -0
  388. package/node_modules/zod/src/v4/locales/tk.ts +2 -0
  389. package/node_modules/zod/src/v4/locales/tr.ts +2 -0
  390. package/node_modules/zod/src/v4/locales/uk.ts +2 -0
  391. package/node_modules/zod/src/v4/locales/ur.ts +2 -0
  392. package/node_modules/zod/src/v4/locales/uz.ts +2 -0
  393. package/node_modules/zod/src/v4/locales/vi.ts +2 -0
  394. package/node_modules/zod/src/v4/locales/yo.ts +2 -0
  395. package/node_modules/zod/src/v4/locales/zh-CN.ts +2 -0
  396. package/node_modules/zod/src/v4/locales/zh-TW.ts +2 -0
  397. package/node_modules/zod/src/v4/mini/external.ts +2 -0
  398. package/node_modules/zod/src/v4/mini/schemas.ts +32 -7
  399. package/node_modules/zod/src/v4/mini/tests/checks.test.ts +1 -1
  400. package/node_modules/zod/src/v4/mini/tests/computed.test.ts +11 -17
  401. package/node_modules/zod/src/v4/mini/tests/index.test.ts +86 -0
  402. package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +16 -0
  403. package/node_modules/zod/src/v4/mini/tests/string.test.ts +23 -0
  404. package/node_modules/zod/v3/ZodError.cjs +19 -0
  405. package/node_modules/zod/v3/errors.cjs +19 -0
  406. package/node_modules/zod/v3/external.cjs +19 -0
  407. package/node_modules/zod/v3/helpers/enumUtil.cjs +19 -0
  408. package/node_modules/zod/v3/helpers/errorUtil.cjs +20 -1
  409. package/node_modules/zod/v3/helpers/errorUtil.js +1 -1
  410. package/node_modules/zod/v3/helpers/parseUtil.cjs +19 -0
  411. package/node_modules/zod/v3/helpers/partialUtil.cjs +19 -0
  412. package/node_modules/zod/v3/helpers/typeAliases.cjs +19 -0
  413. package/node_modules/zod/v3/helpers/util.cjs +19 -0
  414. package/node_modules/zod/v3/index.cjs +19 -0
  415. package/node_modules/zod/v3/standard-schema.cjs +19 -0
  416. package/node_modules/zod/v3/types.cjs +19 -0
  417. package/node_modules/zod/v4/classic/checks.cjs +19 -0
  418. package/node_modules/zod/v4/classic/coerce.cjs +19 -0
  419. package/node_modules/zod/v4/classic/compat.cjs +19 -0
  420. package/node_modules/zod/v4/classic/deep-partial.cjs +19 -0
  421. package/node_modules/zod/v4/classic/errors.cjs +19 -0
  422. package/node_modules/zod/v4/classic/external.cjs +22 -1
  423. package/node_modules/zod/v4/classic/external.d.cts +1 -1
  424. package/node_modules/zod/v4/classic/external.d.ts +1 -1
  425. package/node_modules/zod/v4/classic/external.js +1 -1
  426. package/node_modules/zod/v4/classic/from-json-schema.cjs +264 -24
  427. package/node_modules/zod/v4/classic/from-json-schema.js +245 -24
  428. package/node_modules/zod/v4/classic/in-out.cjs +19 -0
  429. package/node_modules/zod/v4/classic/index.cjs +19 -0
  430. package/node_modules/zod/v4/classic/iso.cjs +19 -0
  431. package/node_modules/zod/v4/classic/parse.cjs +19 -0
  432. package/node_modules/zod/v4/classic/schemas.cjs +100 -35
  433. package/node_modules/zod/v4/classic/schemas.d.cts +15 -1
  434. package/node_modules/zod/v4/classic/schemas.d.ts +15 -1
  435. package/node_modules/zod/v4/classic/schemas.js +77 -33
  436. package/node_modules/zod/v4/core/api.cjs +45 -22
  437. package/node_modules/zod/v4/core/api.d.cts +12 -6
  438. package/node_modules/zod/v4/core/api.d.ts +12 -6
  439. package/node_modules/zod/v4/core/api.js +25 -22
  440. package/node_modules/zod/v4/core/checks.cjs +51 -97
  441. package/node_modules/zod/v4/core/checks.d.cts +17 -1
  442. package/node_modules/zod/v4/core/checks.d.ts +17 -1
  443. package/node_modules/zod/v4/core/checks.js +31 -96
  444. package/node_modules/zod/v4/core/compile.cjs +173 -78
  445. package/node_modules/zod/v4/core/compile.d.cts +18 -4
  446. package/node_modules/zod/v4/core/compile.d.ts +18 -4
  447. package/node_modules/zod/v4/core/compile.js +154 -79
  448. package/node_modules/zod/v4/core/core.cjs +20 -1
  449. package/node_modules/zod/v4/core/core.js +1 -1
  450. package/node_modules/zod/v4/core/doc.cjs +26 -2
  451. package/node_modules/zod/v4/core/doc.js +7 -2
  452. package/node_modules/zod/v4/core/errors.cjs +21 -5
  453. package/node_modules/zod/v4/core/errors.js +2 -5
  454. package/node_modules/zod/v4/core/index.cjs +19 -0
  455. package/node_modules/zod/v4/core/json-schema-generator.cjs +20 -1
  456. package/node_modules/zod/v4/core/json-schema-generator.js +2 -2
  457. package/node_modules/zod/v4/core/json-schema-processors.cjs +188 -72
  458. package/node_modules/zod/v4/core/json-schema-processors.d.cts +16 -0
  459. package/node_modules/zod/v4/core/json-schema-processors.d.ts +16 -0
  460. package/node_modules/zod/v4/core/json-schema-processors.js +170 -74
  461. package/node_modules/zod/v4/core/json-schema.cjs +19 -0
  462. package/node_modules/zod/v4/core/memoizer.cjs +111 -23
  463. package/node_modules/zod/v4/core/memoizer.js +69 -23
  464. package/node_modules/zod/v4/core/parse.cjs +56 -16
  465. package/node_modules/zod/v4/core/parse.js +37 -16
  466. package/node_modules/zod/v4/core/regexes.cjs +31 -6
  467. package/node_modules/zod/v4/core/regexes.d.cts +3 -0
  468. package/node_modules/zod/v4/core/regexes.d.ts +3 -0
  469. package/node_modules/zod/v4/core/regexes.js +10 -4
  470. package/node_modules/zod/v4/core/registries.cjs +19 -0
  471. package/node_modules/zod/v4/core/schemas.cjs +302 -114
  472. package/node_modules/zod/v4/core/schemas.d.cts +28 -8
  473. package/node_modules/zod/v4/core/schemas.d.ts +28 -8
  474. package/node_modules/zod/v4/core/schemas.js +279 -113
  475. package/node_modules/zod/v4/core/standard-schema.cjs +19 -0
  476. package/node_modules/zod/v4/core/to-json-schema.cjs +28 -7
  477. package/node_modules/zod/v4/core/to-json-schema.d.cts +4 -3
  478. package/node_modules/zod/v4/core/to-json-schema.d.ts +4 -3
  479. package/node_modules/zod/v4/core/to-json-schema.js +7 -6
  480. package/node_modules/zod/v4/core/util.cjs +177 -143
  481. package/node_modules/zod/v4/core/util.d.cts +25 -4
  482. package/node_modules/zod/v4/core/util.d.ts +25 -4
  483. package/node_modules/zod/v4/core/util.js +156 -143
  484. package/node_modules/zod/v4/core/versions.cjs +21 -2
  485. package/node_modules/zod/v4/core/versions.d.cts +1 -1
  486. package/node_modules/zod/v4/core/versions.d.ts +1 -1
  487. package/node_modules/zod/v4/core/versions.js +2 -2
  488. package/node_modules/zod/v4/core/visit.cjs +19 -0
  489. package/node_modules/zod/v4/index.cjs +19 -0
  490. package/node_modules/zod/v4/locales/ar.cjs +2 -0
  491. package/node_modules/zod/v4/locales/ar.js +2 -0
  492. package/node_modules/zod/v4/locales/az.cjs +2 -0
  493. package/node_modules/zod/v4/locales/az.js +2 -0
  494. package/node_modules/zod/v4/locales/be.cjs +2 -0
  495. package/node_modules/zod/v4/locales/be.js +2 -0
  496. package/node_modules/zod/v4/locales/bg.cjs +2 -0
  497. package/node_modules/zod/v4/locales/bg.js +2 -0
  498. package/node_modules/zod/v4/locales/bn.cjs +2 -0
  499. package/node_modules/zod/v4/locales/bn.js +2 -0
  500. package/node_modules/zod/v4/locales/ca.cjs +2 -0
  501. package/node_modules/zod/v4/locales/ca.js +2 -0
  502. package/node_modules/zod/v4/locales/ckb.cjs +2 -0
  503. package/node_modules/zod/v4/locales/ckb.js +2 -0
  504. package/node_modules/zod/v4/locales/cs.cjs +2 -0
  505. package/node_modules/zod/v4/locales/cs.js +2 -0
  506. package/node_modules/zod/v4/locales/da.cjs +2 -0
  507. package/node_modules/zod/v4/locales/da.js +2 -0
  508. package/node_modules/zod/v4/locales/de.cjs +2 -0
  509. package/node_modules/zod/v4/locales/de.js +2 -0
  510. package/node_modules/zod/v4/locales/el.cjs +2 -0
  511. package/node_modules/zod/v4/locales/el.js +2 -0
  512. package/node_modules/zod/v4/locales/en.cjs +2 -0
  513. package/node_modules/zod/v4/locales/en.js +2 -0
  514. package/node_modules/zod/v4/locales/eo.cjs +2 -0
  515. package/node_modules/zod/v4/locales/eo.js +2 -0
  516. package/node_modules/zod/v4/locales/es.cjs +2 -0
  517. package/node_modules/zod/v4/locales/es.js +2 -0
  518. package/node_modules/zod/v4/locales/fa.cjs +2 -0
  519. package/node_modules/zod/v4/locales/fa.js +2 -0
  520. package/node_modules/zod/v4/locales/fi.cjs +2 -0
  521. package/node_modules/zod/v4/locales/fi.js +2 -0
  522. package/node_modules/zod/v4/locales/fr-CA.cjs +2 -0
  523. package/node_modules/zod/v4/locales/fr-CA.js +2 -0
  524. package/node_modules/zod/v4/locales/fr.cjs +2 -0
  525. package/node_modules/zod/v4/locales/fr.js +2 -0
  526. package/node_modules/zod/v4/locales/gu.cjs +2 -0
  527. package/node_modules/zod/v4/locales/gu.js +2 -0
  528. package/node_modules/zod/v4/locales/he.cjs +2 -0
  529. package/node_modules/zod/v4/locales/he.js +2 -0
  530. package/node_modules/zod/v4/locales/hi.cjs +2 -0
  531. package/node_modules/zod/v4/locales/hi.js +2 -0
  532. package/node_modules/zod/v4/locales/hr.cjs +2 -0
  533. package/node_modules/zod/v4/locales/hr.js +2 -0
  534. package/node_modules/zod/v4/locales/hu.cjs +2 -0
  535. package/node_modules/zod/v4/locales/hu.js +2 -0
  536. package/node_modules/zod/v4/locales/hy.cjs +2 -0
  537. package/node_modules/zod/v4/locales/hy.js +2 -0
  538. package/node_modules/zod/v4/locales/id.cjs +2 -0
  539. package/node_modules/zod/v4/locales/id.js +2 -0
  540. package/node_modules/zod/v4/locales/index.cjs +22 -1
  541. package/node_modules/zod/v4/locales/index.d.cts +1 -0
  542. package/node_modules/zod/v4/locales/index.d.ts +1 -0
  543. package/node_modules/zod/v4/locales/index.js +1 -0
  544. package/node_modules/zod/v4/locales/is.cjs +2 -0
  545. package/node_modules/zod/v4/locales/is.js +2 -0
  546. package/node_modules/zod/v4/locales/it.cjs +2 -0
  547. package/node_modules/zod/v4/locales/it.js +2 -0
  548. package/node_modules/zod/v4/locales/ja.cjs +2 -0
  549. package/node_modules/zod/v4/locales/ja.js +2 -0
  550. package/node_modules/zod/v4/locales/ka.cjs +2 -0
  551. package/node_modules/zod/v4/locales/ka.js +2 -0
  552. package/node_modules/zod/v4/locales/km.cjs +2 -0
  553. package/node_modules/zod/v4/locales/km.js +2 -0
  554. package/node_modules/zod/v4/locales/kn.cjs +2 -0
  555. package/node_modules/zod/v4/locales/kn.js +2 -0
  556. package/node_modules/zod/v4/locales/ko.cjs +2 -0
  557. package/node_modules/zod/v4/locales/ko.js +2 -0
  558. package/node_modules/zod/v4/locales/lt.cjs +2 -0
  559. package/node_modules/zod/v4/locales/lt.js +2 -0
  560. package/node_modules/zod/v4/locales/mk.cjs +2 -0
  561. package/node_modules/zod/v4/locales/mk.js +2 -0
  562. package/node_modules/zod/v4/locales/ms.cjs +2 -0
  563. package/node_modules/zod/v4/locales/ms.js +2 -0
  564. package/node_modules/zod/v4/locales/ne.cjs +2 -0
  565. package/node_modules/zod/v4/locales/ne.js +2 -0
  566. package/node_modules/zod/v4/locales/nl.cjs +2 -0
  567. package/node_modules/zod/v4/locales/nl.js +2 -0
  568. package/node_modules/zod/v4/locales/nn.cjs +2 -0
  569. package/node_modules/zod/v4/locales/nn.js +2 -0
  570. package/node_modules/zod/v4/locales/no.cjs +2 -0
  571. package/node_modules/zod/v4/locales/no.js +2 -0
  572. package/node_modules/zod/v4/locales/ota.cjs +2 -0
  573. package/node_modules/zod/v4/locales/ota.js +2 -0
  574. package/node_modules/zod/v4/locales/pl.cjs +2 -0
  575. package/node_modules/zod/v4/locales/pl.js +2 -0
  576. package/node_modules/zod/v4/locales/ps.cjs +2 -0
  577. package/node_modules/zod/v4/locales/ps.js +2 -0
  578. package/node_modules/zod/v4/locales/pt-BR.cjs +2 -0
  579. package/node_modules/zod/v4/locales/pt-BR.js +2 -0
  580. package/node_modules/zod/v4/locales/pt.cjs +2 -0
  581. package/node_modules/zod/v4/locales/pt.js +2 -0
  582. package/node_modules/zod/v4/locales/ro.cjs +2 -0
  583. package/node_modules/zod/v4/locales/ro.js +2 -0
  584. package/node_modules/zod/v4/locales/ru.cjs +2 -0
  585. package/node_modules/zod/v4/locales/ru.js +2 -0
  586. package/node_modules/zod/v4/locales/sk.cjs +2 -0
  587. package/node_modules/zod/v4/locales/sk.js +2 -0
  588. package/node_modules/zod/v4/locales/sl.cjs +2 -0
  589. package/node_modules/zod/v4/locales/sl.js +2 -0
  590. package/node_modules/zod/v4/locales/sv.cjs +2 -0
  591. package/node_modules/zod/v4/locales/sv.js +2 -0
  592. package/node_modules/zod/v4/locales/ta.cjs +2 -0
  593. package/node_modules/zod/v4/locales/ta.js +2 -0
  594. package/node_modules/zod/v4/locales/tg.cjs +144 -0
  595. package/node_modules/zod/v4/locales/tg.d.cts +5 -0
  596. package/node_modules/zod/v4/locales/tg.d.ts +4 -0
  597. package/node_modules/zod/v4/locales/tg.js +117 -0
  598. package/node_modules/zod/v4/locales/th.cjs +2 -0
  599. package/node_modules/zod/v4/locales/th.js +2 -0
  600. package/node_modules/zod/v4/locales/tk.cjs +2 -0
  601. package/node_modules/zod/v4/locales/tk.js +2 -0
  602. package/node_modules/zod/v4/locales/tr.cjs +2 -0
  603. package/node_modules/zod/v4/locales/tr.js +2 -0
  604. package/node_modules/zod/v4/locales/uk.cjs +2 -0
  605. package/node_modules/zod/v4/locales/uk.js +2 -0
  606. package/node_modules/zod/v4/locales/ur.cjs +2 -0
  607. package/node_modules/zod/v4/locales/ur.js +2 -0
  608. package/node_modules/zod/v4/locales/uz.cjs +2 -0
  609. package/node_modules/zod/v4/locales/uz.js +2 -0
  610. package/node_modules/zod/v4/locales/vi.cjs +2 -0
  611. package/node_modules/zod/v4/locales/vi.js +2 -0
  612. package/node_modules/zod/v4/locales/yo.cjs +2 -0
  613. package/node_modules/zod/v4/locales/yo.js +2 -0
  614. package/node_modules/zod/v4/locales/zh-CN.cjs +2 -0
  615. package/node_modules/zod/v4/locales/zh-CN.js +2 -0
  616. package/node_modules/zod/v4/locales/zh-TW.cjs +2 -0
  617. package/node_modules/zod/v4/locales/zh-TW.js +2 -0
  618. package/node_modules/zod/v4/mini/checks.cjs +19 -0
  619. package/node_modules/zod/v4/mini/coerce.cjs +19 -0
  620. package/node_modules/zod/v4/mini/deep-partial.cjs +19 -0
  621. package/node_modules/zod/v4/mini/external.cjs +22 -1
  622. package/node_modules/zod/v4/mini/external.d.cts +1 -1
  623. package/node_modules/zod/v4/mini/external.d.ts +1 -1
  624. package/node_modules/zod/v4/mini/external.js +1 -1
  625. package/node_modules/zod/v4/mini/in-out.cjs +19 -0
  626. package/node_modules/zod/v4/mini/index.cjs +19 -0
  627. package/node_modules/zod/v4/mini/iso.cjs +19 -0
  628. package/node_modules/zod/v4/mini/parse.cjs +19 -0
  629. package/node_modules/zod/v4/mini/schemas.cjs +44 -8
  630. package/node_modules/zod/v4/mini/schemas.d.cts +6 -1
  631. package/node_modules/zod/v4/mini/schemas.d.ts +6 -1
  632. package/node_modules/zod/v4/mini/schemas.js +21 -6
  633. package/node_modules/zod/v4-mini/index.cjs +19 -0
  634. package/openclaw.plugin.json +49 -3
  635. package/package.json +8 -8
  636. package/dist/.setup/accounts.runtime-BpWv-6-2.mjs +0 -2
  637. package/dist/.setup/action-runtime.runtime-DwH3NdpT.mjs +0 -2
  638. package/dist/.setup/doctor-contract-CtMUqjvk.mjs +0 -186
  639. package/dist/.setup/monitor-Dw5uuKWM.mjs +0 -13
  640. package/dist/.setup/rolldown-runtime-D7D4PA-g.mjs +0 -13
  641. package/dist/.setup/send.runtime-BmqRP-WG.mjs +0 -2
  642. package/dist/.setup/slash-commands.runtime-BpSH0b3q.mjs +0 -2
  643. package/dist/.setup/slash-skill-commands.runtime-Bi1JWZHY.mjs +0 -2
  644. package/node_modules/undici/lib/handler/unwrap-handler.js +0 -106
  645. package/node_modules/undici/lib/handler/wrap-handler.js +0 -105
  646. package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  647. package/node_modules/undici/lib/util/promise.js +0 -28
  648. /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
@@ -10,7 +10,8 @@ const {
10
10
  InformationalError,
11
11
  InvalidArgumentError,
12
12
  HeadersTimeoutError,
13
- BodyTimeoutError
13
+ BodyTimeoutError,
14
+ ResponseExceededMaxSizeError
14
15
  } = require('../core/errors.js')
15
16
  const {
16
17
  kUrl,
@@ -26,24 +27,38 @@ const {
26
27
  kStrictContentLength,
27
28
  kOnError,
28
29
  kMaxConcurrentStreams,
29
- kPingInterval,
30
30
  kHTTP2Session,
31
- kHTTP2InitialWindowSize,
32
- kHTTP2ConnectionWindowSize,
31
+ kHostAuthority,
33
32
  kResume,
34
33
  kSize,
35
34
  kHTTPContext,
36
35
  kClosed,
37
- kBodyTimeout,
36
+ kKeepAliveDefaultTimeout,
38
37
  kHeadersTimeout,
38
+ kBodyTimeout,
39
39
  kEnableConnectProtocol,
40
40
  kRemoteSettings,
41
41
  kHTTP2Stream,
42
- kHTTP2SessionState
42
+ kHTTP2SessionState,
43
+ kHTTP2Options,
44
+ kMaxResponseSize
43
45
  } = require('../core/symbols.js')
44
46
  const { channels } = require('../core/diagnostics.js')
45
47
 
46
48
  const kOpenStreams = Symbol('open streams')
49
+ const kRequestStreamId = Symbol('request stream id')
50
+ const kRequestStream = Symbol('request stream')
51
+ const kRequestStreamCleanup = Symbol('request stream cleanup')
52
+ const kRequestStreamState = Symbol('request stream state')
53
+ const kReceivedGoAway = Symbol('received goaway')
54
+ const kGoAwayReplayAttempts = Symbol('goaway replay attempts')
55
+ const kRefusedStreamRetry = Symbol('refused stream retry')
56
+
57
+ // RFC 9113 section 8.7: a client SHOULD NOT automatically retry a request more
58
+ // than once. Without a budget a peer that keeps refusing turns one request into
59
+ // an unbounded connect/refuse/reconnect loop that never settles and starves the
60
+ // event loop.
61
+ const MAX_GOAWAY_REPLAY_ATTEMPTS = 1
47
62
 
48
63
  let extractBody
49
64
 
@@ -66,40 +81,180 @@ const {
66
81
  HTTP2_HEADER_EXPECT,
67
82
  HTTP2_HEADER_STATUS,
68
83
  HTTP2_HEADER_PROTOCOL,
69
- NGHTTP2_REFUSED_STREAM,
70
- NGHTTP2_CANCEL
84
+ NGHTTP2_NO_ERROR,
85
+ NGHTTP2_REFUSED_STREAM
71
86
  }
72
87
  } = http2
73
88
 
74
- function parseH2Headers (headers) {
75
- const result = []
76
-
77
- for (const [name, value] of Object.entries(headers)) {
78
- // h2 may concat the header value by array
79
- // e.g. Set-Cookie
80
- if (Array.isArray(value)) {
81
- for (const subvalue of value) {
82
- // we need to provide each header value of header name
83
- // because the headers handler expect name-value pair
84
- result.push(Buffer.from(name), Buffer.from(subvalue))
85
- }
86
- } else {
87
- result.push(Buffer.from(name), Buffer.from(value))
89
+ function getGoAwayError (session, errorCode) {
90
+ return session[kError] ||
91
+ (errorCode === NGHTTP2_NO_ERROR
92
+ ? new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`)
93
+ : new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(session[kSocket])))
94
+ }
95
+
96
+ function resetHttp2Session (session, err) {
97
+ const client = session[kClient]
98
+ const socket = session[kSocket]
99
+
100
+ if (client[kHTTP2Session] === session) {
101
+ client[kSocket] = null
102
+ client[kHTTPContext] = null
103
+ client[kHTTP2Session] = null
104
+ }
105
+
106
+ if (socket != null && socket[kError] == null) {
107
+ socket[kError] = err
108
+ }
109
+
110
+ if (!session.closed && !session.destroyed) {
111
+ try {
112
+ session.destroy(err)
113
+ } catch {}
114
+ }
115
+
116
+ util.destroy(socket, err)
117
+ }
118
+
119
+ function getGoAwayPendingIdx (client, lastStreamID) {
120
+ const maxAcceptedStreamID = Number.isInteger(lastStreamID) ? lastStreamID : Number.MAX_SAFE_INTEGER
121
+
122
+ for (let i = client[kRunningIdx]; i < client[kPendingIdx]; i++) {
123
+ const request = client[kQueue][i]
124
+
125
+ if (request == null) {
126
+ continue
127
+ }
128
+
129
+ if (typeof request[kRequestStreamId] !== 'number' || request[kRequestStreamId] > maxAcceptedStreamID) {
130
+ return i
88
131
  }
89
132
  }
90
133
 
91
- return result
134
+ return client[kPendingIdx]
135
+ }
136
+
137
+ function detachRequestFromStream (request) {
138
+ request[kRequestStreamId] = null
139
+ request[kRequestStream] = null
140
+ request[kRequestStreamCleanup] = null
141
+ }
142
+
143
+ function bindRequestToStream (request, stream, cleanup) {
144
+ const previousCleanup = request[kRequestStreamCleanup]
145
+ const previousStream = request[kRequestStream]
146
+ detachRequestFromStream(request)
147
+ previousCleanup?.(previousStream)
148
+ request[kRequestStreamId] = stream.id
149
+ request[kRequestStream] = stream
150
+ request[kRequestStreamCleanup] = cleanup
151
+ }
152
+
153
+ function clearRequestStream (request) {
154
+ const cleanup = request[kRequestStreamCleanup]
155
+ const stream = request[kRequestStream]
156
+ detachRequestFromStream(request)
157
+ cleanup?.(stream)
158
+ }
159
+
160
+ function requeueUnsentRequest (client, request) {
161
+ client[kQueue].splice(client[kPendingIdx] + 1, 0, request)
162
+ }
163
+
164
+ function completeRequest (client, request, resetPendingIdx = false) {
165
+ const queue = client[kQueue]
166
+ const runningIdx = client[kRunningIdx]
167
+
168
+ // In-order completion: clear the request and advance without splicing.
169
+ // The client's resume loop compacts cleared slots once the index grows.
170
+ if (runningIdx < client[kPendingIdx] && queue[runningIdx] === request) {
171
+ queue[runningIdx] = null
172
+ client[kRunningIdx] = runningIdx + 1
173
+ return
174
+ }
175
+
176
+ const index = queue.indexOf(request, runningIdx)
177
+
178
+ if (index === -1 || index >= client[kPendingIdx]) {
179
+ return
180
+ }
181
+
182
+ queue.splice(index, 1)
183
+ client[kPendingIdx]--
184
+
185
+ if (resetPendingIdx && client[kPendingIdx] < client[kRunningIdx]) {
186
+ client[kPendingIdx] = client[kRunningIdx]
187
+ }
188
+ }
189
+
190
+ function canReplayRequest (request) {
191
+ const { body } = request
192
+
193
+ return body == null || util.isBuffer(body) || util.isBlobLike(body)
194
+ }
195
+
196
+ // Count a GOAWAY refusal against the request's replay budget. A peer that
197
+ // refuses every connection must eventually surface an error to the caller
198
+ // rather than being retried forever. Kept separate from canReplayRequest so
199
+ // that the REFUSED_STREAM retry, which has its own single-attempt limit, does
200
+ // not consume this budget just by asking whether the body can be replayed.
201
+ function registerGoAwayRefusal (request) {
202
+ const attempts = (request[kGoAwayReplayAttempts] ?? 0) + 1
203
+ request[kGoAwayReplayAttempts] = attempts
204
+
205
+ return attempts <= MAX_GOAWAY_REPLAY_ATTEMPTS
206
+ }
207
+
208
+ function closeStream (stream, code = NGHTTP2_REFUSED_STREAM) {
209
+ if (stream != null && !stream.destroyed && !stream.closed) {
210
+ try {
211
+ stream.close(code)
212
+ } catch {}
213
+ }
214
+ }
215
+
216
+ function detachRequestStreamForClose (request) {
217
+ const stream = request[kRequestStream]
218
+
219
+ clearRequestStream(request)
220
+ severRequestStream(stream)
221
+
222
+ return stream
223
+ }
224
+
225
+ // Unbind a stream from its request for good. releaseRequestStream() alone
226
+ // leaves the 'close' listener attached and kRequestStreamState populated, so a
227
+ // stream abandoned here would still run completeRequestStream() later — and
228
+ // splice out the request that has since been requeued onto another session.
229
+ function severRequestStream (stream) {
230
+ if (stream == null || stream[kRequestStreamState] == null) {
231
+ return
232
+ }
233
+
234
+ stream[kRequestStreamState] = null
235
+ stream.off('close', completeRequestStream)
236
+ // Upgrade streams use their own close cleanup, which would otherwise release
237
+ // the session a second time after the stream has been severed for GOAWAY.
238
+ stream.off('close', onUpgradeStreamClose)
239
+
240
+ if (stream[kHTTP2Session] != null) {
241
+ closeStreamSession(stream)
242
+ }
243
+
244
+ if (!stream.destroyed && !stream.closed) {
245
+ stream.once('error', noop)
246
+ }
92
247
  }
93
248
 
94
249
  function connectH2 (client, socket) {
95
250
  client[kSocket] = socket
96
251
 
97
- const http2InitialWindowSize = client[kHTTP2InitialWindowSize]
98
- const http2ConnectionWindowSize = client[kHTTP2ConnectionWindowSize]
252
+ const http2InitialWindowSize = client[kHTTP2Options].sessionOptions?.initialWindowSize
253
+ const http2ConnectionWindowSize = client[kHTTP2Options].connectionWindowSize
99
254
 
100
255
  const session = http2.connect(client[kUrl], {
101
256
  createConnection: () => socket,
102
- peerMaxConcurrentStreams: client[kMaxConcurrentStreams],
257
+ peerMaxConcurrentStreams: client[kHTTP2Options].maxConcurrentStreams,
103
258
  settings: {
104
259
  // TODO(metcoder95): add support for PUSH
105
260
  enablePush: false,
@@ -112,10 +267,20 @@ function connectH2 (client, socket) {
112
267
  session[kClient] = client
113
268
  session[kSocket] = socket
114
269
  session[kHTTP2SessionState] = {
270
+ idleTimeout: null,
271
+ // Armed while the peer advertises MAX_CONCURRENT_STREAMS = 0 and we have
272
+ // work that cannot start. See setNoStreamsTimeout.
273
+ noStreamsTimeout: null,
274
+ // Sockets start out ref'd. Session ref/unref proxies to the socket, so a
275
+ // single cached flag lets us skip redundant uv ref/unref calls, provided
276
+ // every ref/unref of the session or its socket goes through
277
+ // refH2Session/unrefH2Session.
278
+ refed: true,
115
279
  ping: {
116
- interval: client[kPingInterval] === 0 ? null : setInterval(onHttp2SendPing, client[kPingInterval], session).unref()
280
+ interval: client[kHTTP2Options].pingInterval === 0 ? null : setInterval(onHttp2SendPing, client[kHTTP2Options].pingInterval, session).unref()
117
281
  }
118
282
  }
283
+ session[kReceivedGoAway] = false
119
284
  // We set it to true by default in a best-effort; however once connected to an H2 server
120
285
  // we will check if extended CONNECT protocol is supported or not
121
286
  // and set this value accordingly.
@@ -130,14 +295,13 @@ function connectH2 (client, socket) {
130
295
 
131
296
  util.addListener(session, 'error', onHttp2SessionError)
132
297
  util.addListener(session, 'frameError', onHttp2FrameError)
133
- util.addListener(session, 'end', onHttp2SessionEnd)
134
298
  util.addListener(session, 'goaway', onHttp2SessionGoAway)
135
299
  util.addListener(session, 'close', onHttp2SessionClose)
136
300
  util.addListener(session, 'remoteSettings', onHttp2RemoteSettings)
137
301
  // TODO (@metcoder95): implement SETTINGS support
138
302
  // util.addListener(session, 'localSettings', onHttp2RemoteSettings)
139
303
 
140
- session.unref()
304
+ unrefH2Session(session)
141
305
 
142
306
  client[kHTTP2Session] = session
143
307
  socket[kHTTP2Session] = session
@@ -187,27 +351,25 @@ function connectH2 (client, socket) {
187
351
  * @returns {boolean}
188
352
  */
189
353
  busy (request) {
354
+ if (session[kRemoteSettings] === false && client[kRunning] > 0) {
355
+ return true
356
+ }
357
+
358
+ if (client[kRunning] >= client[kMaxConcurrentStreams]) {
359
+ return true
360
+ }
361
+
190
362
  if (request != null) {
191
363
  if (client[kRunning] > 0) {
192
364
  // We are already processing requests
193
365
 
194
- // Non-idempotent request cannot be retried.
195
- // Ensure that no other requests are inflight and
196
- // could cause failure.
197
- if (request.idempotent === false) return true
366
+ // Unlike HTTP/1.1 pipelining, HTTP/2 multiplexes requests on
367
+ // independent streams, so non-idempotent requests can be dispatched
368
+ // concurrently. Retry eligibility is handled by stream/session error
369
+ // handling instead of by serializing all non-idempotent requests.
198
370
  // Don't dispatch an upgrade until all preceding requests have completed.
199
371
  // Possibly, we do not have remote settings confirmed yet.
200
372
  if ((request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false) return true
201
- // Request with stream or iterator body can error while other requests
202
- // are inflight and indirectly error those as well.
203
- // Ensure this doesn't happen by waiting for inflight
204
- // to complete before dispatching.
205
-
206
- // Request with stream or iterator body cannot be retried.
207
- // Ensure that no other requests are inflight and
208
- // could cause failure.
209
- if (util.bodyLength(request.body) !== 0 &&
210
- (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) return true
211
373
  } else {
212
374
  return (request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false
213
375
  }
@@ -218,22 +380,154 @@ function connectH2 (client, socket) {
218
380
  }
219
381
  }
220
382
 
383
+ // Session ref/unref proxies to the underlying socket, so refH2Session and
384
+ // unrefH2Session cover both and can skip the call when the cached ref state
385
+ // already matches.
386
+ function refH2Session (session) {
387
+ const state = session[kHTTP2SessionState]
388
+
389
+ if (state.refed === false) {
390
+ state.refed = true
391
+ session.ref()
392
+ }
393
+ }
394
+
395
+ function unrefH2Session (session) {
396
+ const state = session[kHTTP2SessionState]
397
+
398
+ if (state.refed === true) {
399
+ state.refed = false
400
+ session.unref()
401
+ }
402
+ }
403
+
221
404
  function resumeH2 (client) {
222
405
  const socket = client[kSocket]
406
+ const session = client[kHTTP2Session]
223
407
 
224
408
  if (socket?.destroyed === false) {
225
- // Only let the process exit when there is genuinely nothing outstanding.
226
- // Unreffing because the peer advertised MAX_CONCURRENT_STREAMS = 0 left
227
- // queued requests with nothing holding the event loop open, so the process
228
- // could exit with status 0 while an awaited request never settled.
229
- if (client[kSize] === 0) {
230
- socket.unref()
231
- client[kHTTP2Session].unref()
409
+ if (client[kSize] === 0 || client[kMaxConcurrentStreams] === 0) {
410
+ unrefH2Session(session)
411
+ } else {
412
+ refH2Session(session)
413
+ }
414
+
415
+ if (client[kSize] === 0 && session[kOpenStreams] === 0) {
416
+ setHttp2IdleTimeout(session)
417
+ } else {
418
+ clearHttp2IdleTimeout(session)
419
+ }
420
+
421
+ if (client[kMaxConcurrentStreams] === 0 && client[kRunning] === 0 && client[kPending] > 0) {
422
+ setNoStreamsTimeout(session)
232
423
  } else {
233
- socket.ref()
234
- client[kHTTP2Session].ref()
424
+ clearNoStreamsTimeout(session)
425
+ }
426
+ }
427
+ }
428
+
429
+ function clearNoStreamsTimeout (session) {
430
+ const state = session[kHTTP2SessionState]
431
+
432
+ if (state?.noStreamsTimeout != null) {
433
+ clearTimeout(state.noStreamsTimeout)
434
+ state.noStreamsTimeout = null
435
+ }
436
+ }
437
+
438
+ // A peer is allowed to advertise SETTINGS_MAX_CONCURRENT_STREAMS = 0 to refuse
439
+ // new streams (RFC 9113 §6.5.2), and is expected to raise it again later. Until
440
+ // it does, busy() reports the client as permanently busy and queued requests
441
+ // cannot open a stream — which means no per-stream timeout covers them, and no
442
+ // reconnect can happen either, so the SETTINGS frame that would lift the limit
443
+ // can never arrive. Give the peer headersTimeout to start honouring requests
444
+ // before failing them; a request that cannot even be sent has missed the same
445
+ // deadline as one whose headers never arrive.
446
+ function setNoStreamsTimeout (session) {
447
+ const client = session[kClient]
448
+ const state = session[kHTTP2SessionState]
449
+ const timeout = client[kHeadersTimeout]
450
+
451
+ if (!timeout || state.noStreamsTimeout != null) {
452
+ return
453
+ }
454
+
455
+ state.noStreamsTimeout = setTimeout(onNoStreamsTimeout, timeout, session).unref()
456
+ }
457
+
458
+ function onNoStreamsTimeout (session) {
459
+ const client = session[kClient]
460
+ const state = session[kHTTP2SessionState]
461
+
462
+ state.noStreamsTimeout = null
463
+
464
+ if (
465
+ client[kHTTP2Session] !== session ||
466
+ client[kMaxConcurrentStreams] !== 0 ||
467
+ client[kRunning] !== 0 ||
468
+ client[kPending] === 0
469
+ ) {
470
+ return
471
+ }
472
+
473
+ const err = new HeadersTimeoutError(
474
+ `HTTP/2: server did not accept a new stream within ${client[kHeadersTimeout]}`
475
+ )
476
+
477
+ const requests = client[kQueue].splice(client[kPendingIdx])
478
+ for (let i = 0; i < requests.length; i++) {
479
+ if (requests[i] != null) {
480
+ util.errorRequest(client, requests[i], err)
235
481
  }
236
482
  }
483
+
484
+ // Drop the unusable session so the next request gets a fresh connection,
485
+ // whose SETTINGS may well allow streams again.
486
+ session[kError] = err
487
+ resetHttp2Session(session, err)
488
+ }
489
+
490
+ function clearHttp2IdleTimeout (session) {
491
+ const state = session[kHTTP2SessionState]
492
+
493
+ if (state?.idleTimeout != null) {
494
+ clearTimeout(state.idleTimeout)
495
+ state.idleTimeout = null
496
+ }
497
+ }
498
+
499
+ function setHttp2IdleTimeout (session) {
500
+ const client = session[kClient]
501
+
502
+ if (client[kHTTP2Session] !== session || session.closed || session.destroyed) {
503
+ return
504
+ }
505
+
506
+ if (session[kOpenStreams] !== 0 || client[kSize] !== 0) {
507
+ clearHttp2IdleTimeout(session)
508
+ return
509
+ }
510
+
511
+ const state = session[kHTTP2SessionState]
512
+ if (state.idleTimeout == null) {
513
+ state.idleTimeout = setTimeout(onHttp2SessionIdleTimeout, client[kKeepAliveDefaultTimeout], session).unref()
514
+ }
515
+ }
516
+
517
+ function onHttp2SessionIdleTimeout (session) {
518
+ const client = session[kClient]
519
+ const socket = session[kSocket]
520
+ const state = session[kHTTP2SessionState]
521
+
522
+ state.idleTimeout = null
523
+
524
+ if (client[kHTTP2Session] !== session || session[kOpenStreams] !== 0 || client[kSize] !== 0 || session.closed || session.destroyed) {
525
+ return
526
+ }
527
+
528
+ const err = new InformationalError('socket idle timeout')
529
+ socket[kError] = err
530
+ util.destroy(socket, err)
237
531
  }
238
532
 
239
533
  function applyConnectionWindowSize (connectionWindowSize) {
@@ -280,7 +574,7 @@ function onHttp2SendPing (session) {
280
574
 
281
575
  function onPing (err, duration) {
282
576
  const client = this[kClient]
283
- const socket = this[kClient]
577
+ const socket = this[kSocket]
284
578
 
285
579
  if (err != null) {
286
580
  const error = new InformationalError(`HTTP/2: "PING" errored - type ${err.message}`)
@@ -296,23 +590,26 @@ function onHttp2SessionError (err) {
296
590
  assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
297
591
 
298
592
  this[kSocket][kError] = err
593
+
594
+ if (this[kReceivedGoAway]) {
595
+ return
596
+ }
597
+
299
598
  this[kClient][kOnError](err)
300
599
  }
301
600
 
302
601
  function onHttp2FrameError (type, code, id) {
303
602
  if (id === 0) {
603
+ if (this[kReceivedGoAway]) {
604
+ return
605
+ }
606
+
304
607
  const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
305
608
  this[kSocket][kError] = err
306
609
  this[kClient][kOnError](err)
307
610
  }
308
611
  }
309
612
 
310
- function onHttp2SessionEnd () {
311
- const err = new SocketError('other side closed', util.getSocketInfo(this[kSocket]))
312
- this.destroy(err)
313
- util.destroy(this[kSocket], err)
314
- }
315
-
316
613
  /**
317
614
  * This is the root cause of #3011
318
615
  * We need to handle GOAWAY frames properly, and trigger the session close
@@ -320,80 +617,82 @@ function onHttp2SessionEnd () {
320
617
  *
321
618
  * @this {import('http2').ClientHttp2Session}
322
619
  * @param {number} errorCode
620
+ * @param {number} lastStreamID
323
621
  */
324
- // Backport of #5410 and #5569. HTTP/2 multiplexes, so requests complete out of
325
- // order; advancing kRunningIdx blindly retired whichever request happened to
326
- // sit at the head instead of the one that actually finished, which both lost
327
- // requests and left phantom running slots behind.
328
- function completeRequest (client, request, resetPendingIdx = false) {
329
- const queue = client[kQueue]
330
- const runningIdx = client[kRunningIdx]
331
-
332
- // In-order completion: clear the request and advance without splicing.
333
- // The client's resume loop compacts cleared slots once the index grows.
334
- if (runningIdx < client[kPendingIdx] && queue[runningIdx] === request) {
335
- queue[runningIdx] = null
336
- client[kRunningIdx] = runningIdx + 1
622
+ function onHttp2SessionGoAway (errorCode, lastStreamID) {
623
+ if (this[kReceivedGoAway]) {
337
624
  return
338
625
  }
339
626
 
340
- const index = queue.indexOf(request, runningIdx)
627
+ this[kReceivedGoAway] = true
341
628
 
342
- if (index === -1 || index >= client[kPendingIdx]) {
343
- return
344
- }
629
+ const err = getGoAwayError(this, errorCode)
630
+ const client = this[kClient]
631
+ const previousPendingIdx = client[kPendingIdx]
632
+ const pendingIdx = getGoAwayPendingIdx(client, lastStreamID)
633
+ const retriableRequests = []
634
+ const streamsToClose = []
345
635
 
346
- queue.splice(index, 1)
347
- client[kPendingIdx]--
636
+ // Closing one stream after GOAWAY can synchronously emit frameError on
637
+ // sibling streams. Detach all affected requests first so those errors do
638
+ // not fail requests that are about to be requeued.
639
+ for (let i = pendingIdx; i < previousPendingIdx; i++) {
640
+ const request = client[kQueue][i]
348
641
 
349
- if (resetPendingIdx && client[kPendingIdx] < client[kRunningIdx]) {
350
- client[kPendingIdx] = client[kRunningIdx]
351
- }
352
- }
642
+ if (request != null) {
643
+ streamsToClose.push(detachRequestStreamForClose(request))
353
644
 
354
- function onHttp2SessionGoAway (errorCode) {
355
- // TODO(mcollina): Verify if GOAWAY implements the spec correctly:
356
- // https://datatracker.ietf.org/doc/html/rfc7540#section-6.8
357
- // Specifically, we do not verify the "valid" stream id.
645
+ if (canReplayRequest(request) && registerGoAwayRefusal(request)) {
646
+ retriableRequests.push(request)
647
+ } else {
648
+ util.errorRequest(client, request, err)
649
+ }
650
+ }
651
+ }
358
652
 
359
- const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(this[kSocket]))
360
- const client = this[kClient]
653
+ for (let i = 0; i < streamsToClose.length; i++) {
654
+ closeStream(streamsToClose[i])
655
+ }
361
656
 
362
- client[kSocket] = null
363
- client[kHTTPContext] = null
657
+ if (pendingIdx !== previousPendingIdx) {
658
+ const remainingPendingRequests = client[kQueue].slice(previousPendingIdx)
659
+ client[kQueue].length = pendingIdx
660
+ client[kQueue].push(...retriableRequests, ...remainingPendingRequests)
661
+ }
364
662
 
365
- // this is an HTTP2 session
366
- this.close()
367
- this[kHTTP2Session] = null
663
+ if (client[kHTTP2Session] === this) {
664
+ client[kSocket] = null
665
+ client[kHTTPContext] = null
666
+ client[kHTTP2Session] = null
667
+ }
368
668
 
369
- util.destroy(this[kSocket], err)
669
+ clearHttp2IdleTimeout(this)
670
+ clearNoStreamsTimeout(this)
370
671
 
371
- // Fail head of pipeline.
372
- if (client[kRunningIdx] < client[kQueue].length) {
373
- const request = client[kQueue][client[kRunningIdx]]
374
- client[kQueue][client[kRunningIdx]++] = null
375
- if (request != null) {
376
- util.errorRequest(client, request, err)
377
- }
378
- client[kPendingIdx] = client[kRunningIdx]
672
+ if (!this.closed && !this.destroyed) {
673
+ this.close()
379
674
  }
380
675
 
381
- assert(client[kRunning] === 0)
676
+ client[kPendingIdx] = pendingIdx
382
677
 
383
678
  client.emit('disconnect', client[kUrl], [client], err)
384
- client.emit('connectionError', client[kUrl], [client], err)
385
679
 
386
680
  client[kResume]()
387
681
  }
388
682
 
389
683
  function onHttp2SessionClose () {
390
- const { [kClient]: client, [kHTTP2SessionState]: state } = this
391
- const { [kSocket]: socket } = client
684
+ const { [kClient]: client, [kHTTP2SessionState]: state, [kSocket]: socket } = this
392
685
 
393
- const err = this[kSocket][kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket))
686
+ const err = socket[kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket))
394
687
 
395
- client[kSocket] = null
396
- client[kHTTPContext] = null
688
+ if (client[kHTTP2Session] === this) {
689
+ client[kSocket] = null
690
+ client[kHTTPContext] = null
691
+ client[kHTTP2Session] = null
692
+ }
693
+
694
+ clearHttp2IdleTimeout(this)
695
+ clearNoStreamsTimeout(this)
397
696
 
398
697
  if (state.ping.interval != null) {
399
698
  clearInterval(state.ping.interval)
@@ -417,15 +716,27 @@ function onHttp2SessionClose () {
417
716
  function onHttp2SocketClose () {
418
717
  const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
419
718
 
420
- const client = this[kHTTP2Session][kClient]
719
+ const session = this[kHTTP2Session]
720
+ const client = session[kClient]
721
+
722
+ if (client[kSocket] !== this) {
723
+ // Ignore stale socket closes from a detached GOAWAY session and from any
724
+ // session that has already been replaced. If the session was detached
725
+ // without a GOAWAY and there is no replacement yet, we still need the
726
+ // close event to flush the client state.
727
+ if (session[kReceivedGoAway] || (client[kHTTP2Session] != null && client[kHTTP2Session] !== session)) {
728
+ return
729
+ }
730
+ }
421
731
 
422
732
  client[kSocket] = null
423
733
  client[kHTTPContext] = null
424
-
425
- if (this[kHTTP2Session] !== null) {
426
- this[kHTTP2Session].destroy(err)
734
+ if (client[kHTTP2Session] === session) {
735
+ client[kHTTP2Session] = null
427
736
  }
428
737
 
738
+ session.destroy(err)
739
+
429
740
  client[kPendingIdx] = client[kRunningIdx]
430
741
 
431
742
  assert(client[kRunning] === 0)
@@ -440,7 +751,11 @@ function onHttp2SocketError (err) {
440
751
 
441
752
  this[kError] = err
442
753
 
443
- this[kClient][kOnError](err)
754
+ if (this[kHTTP2Session]?.[kReceivedGoAway]) {
755
+ return
756
+ }
757
+
758
+ this[kHTTP2Session]?.[kClient]?.[kOnError](err)
444
759
  }
445
760
 
446
761
  function onHttp2SocketEnd () {
@@ -451,33 +766,77 @@ function onSocketClose () {
451
766
  this[kClosed] = true
452
767
  }
453
768
 
454
- // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
455
- function shouldSendContentLength (method) {
456
- return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
769
+ function noop () {}
770
+
771
+ function closeStreamSession (stream) {
772
+ const session = stream[kHTTP2Session]
773
+
774
+ stream[kHTTP2Session] = null
775
+ session[kOpenStreams] -= 1
776
+ if (session[kOpenStreams] === 0) {
777
+ unrefH2Session(session)
778
+ setHttp2IdleTimeout(session)
779
+ }
457
780
  }
458
781
 
459
- function writeH2 (client, request) {
460
- // Time to the response headers, then time between body chunks. Using
461
- // bodyTimeout for both made headersTimeout a no-op over HTTP/2.
462
- const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout]
463
- const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout]
464
- const session = client[kHTTP2Session]
465
- const { method, path, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request
466
- let { body } = request
782
+ function onUpgradeStreamClose () {
783
+ this.off('error', noop)
467
784
 
468
- if (upgrade != null && upgrade !== 'websocket') {
469
- util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`))
470
- return false
785
+ const state = this[kRequestStreamState]
786
+ this[kRequestStreamState] = null
787
+
788
+ failUpgradeStream(state, new InformationalError('HTTP/2: stream closed before response headers'))
789
+ closeStreamSession(this)
790
+ }
791
+
792
+ // Idempotent terminal cleanup, called from both 'end' and 'close': the
793
+ // null-state guard no-ops the later call.
794
+ function completeRequestStream () {
795
+ const state = this[kRequestStreamState]
796
+
797
+ if (state == null) {
798
+ return
799
+ }
800
+
801
+ // Release the stream first so request references are cleared,
802
+ // then complete the response with trailers if available.
803
+ releaseRequestStream(this)
804
+
805
+ if (state.pendingEnd && !state.request.aborted && !state.request.completed) {
806
+ state.request.onResponseEnd(state.trailers || {})
807
+ } else if (!state.request.aborted && !state.request.completed) {
808
+ // The stream closed without a complete response and without reporting an
809
+ // error. finalizeRequest() below frees the queue slot either way, so
810
+ // without this the request would simply vanish and its caller would never
811
+ // hear back.
812
+ util.errorRequest(
813
+ state.client,
814
+ state.request,
815
+ new InformationalError('HTTP/2: stream closed before the response was complete')
816
+ )
471
817
  }
472
818
 
819
+ finalizeRequest(state)
820
+ closeStreamSession(this)
821
+ this[kRequestStreamState] = null
822
+ }
823
+
824
+ // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
825
+ function shouldSendContentLength (method) {
826
+ return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
827
+ }
828
+
829
+ function buildRequestHeaders (reqHeaders) {
473
830
  const headers = {}
831
+
474
832
  for (let n = 0; n < reqHeaders.length; n += 2) {
475
833
  const key = reqHeaders[n + 0]
476
834
  const val = reqHeaders[n + 1]
835
+ const current = headers[key]
477
836
 
478
837
  if (key === 'cookie') {
479
- if (headers[key] != null) {
480
- headers[key] = Array.isArray(headers[key]) ? (headers[key].push(val), headers[key]) : [headers[key], val]
838
+ if (current != null) {
839
+ headers[key] = Array.isArray(current) ? (current.push(val), current) : [current, val]
481
840
  } else {
482
841
  headers[key] = val
483
842
  }
@@ -485,30 +844,204 @@ function writeH2 (client, request) {
485
844
  continue
486
845
  }
487
846
 
488
- if (Array.isArray(val)) {
489
- for (let i = 0; i < val.length; i++) {
490
- if (headers[key]) {
491
- headers[key] += `, ${val[i]}`
492
- } else {
493
- headers[key] = val[i]
494
- }
495
- }
496
- } else if (headers[key]) {
497
- headers[key] += `, ${val}`
498
- } else {
499
- headers[key] = val
847
+ if (typeof val === 'string') {
848
+ headers[key] = current ? `${current}, ${val}` : val
849
+ continue
850
+ }
851
+
852
+ for (let i = 0; i < val.length; i++) {
853
+ headers[key] = headers[key] ? `${headers[key]}, ${val[i]}` : val[i]
500
854
  }
501
855
  }
502
856
 
503
- /** @type {import('node:http2').ClientHttp2Stream} */
504
- let stream = null
857
+ return headers
858
+ }
859
+
860
+ function removeUpgradeStreamListeners (stream) {
861
+ stream.off('response', onUpgradeResponse)
862
+ stream.off('error', onUpgradeStreamError)
863
+ stream.off('end', onUpgradeStreamEnd)
864
+ stream.off('timeout', onUpgradeStreamTimeout)
865
+ stream.off('error', noop)
866
+ }
867
+
868
+ function releaseUpgradeStream (stream) {
869
+ if (stream == null) {
870
+ return
871
+ }
872
+
873
+ const state = stream[kRequestStreamState]
874
+ if (state == null) {
875
+ return
876
+ }
877
+
878
+ const { request } = state
879
+
880
+ if (request[kRequestStream] === stream) {
881
+ detachRequestFromStream(request)
882
+ }
505
883
 
506
- const { hostname, port } = client[kUrl]
884
+ removeUpgradeStreamListeners(stream)
507
885
 
508
- headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}`
886
+ if (!stream.destroyed && !stream.closed) {
887
+ stream.once('error', noop)
888
+ }
889
+ }
890
+
891
+ function failUpgradeStream (state, err) {
892
+ if (state == null) {
893
+ return
894
+ }
895
+
896
+ const { request } = state
897
+ if (state.responseReceived || request.aborted || request.completed) {
898
+ return
899
+ }
900
+
901
+ releaseUpgradeStream(state.stream)
902
+ state.abort(err, true)
903
+ }
904
+
905
+ function onUpgradeStreamError () {
906
+ const state = this[kRequestStreamState]
907
+
908
+ if (typeof this.rstCode === 'number' && this.rstCode !== 0) {
909
+ failUpgradeStream(state, new InformationalError(`HTTP/2: "stream error" received - code ${this.rstCode}`))
910
+ } else {
911
+ failUpgradeStream(state, new InformationalError('HTTP/2: stream errored before response headers'))
912
+ }
913
+ }
914
+
915
+ function onUpgradeStreamEnd () {
916
+ failUpgradeStream(this[kRequestStreamState], new InformationalError('HTTP/2: stream half-closed (remote)'))
917
+ }
918
+
919
+ function onUpgradeStreamTimeout () {
920
+ const state = this[kRequestStreamState]
921
+ failUpgradeStream(state, new InformationalError(`HTTP/2: "stream timeout after ${state.headersTimeout}"`))
922
+ }
923
+
924
+ function onUpgradeResponse (headers, _flags) {
925
+ const stream = this
926
+ const state = stream[kRequestStreamState]
927
+ const { request } = state
928
+
929
+ state.responseReceived = true
930
+
931
+ const statusCode = headers[HTTP2_HEADER_STATUS]
932
+ delete headers[HTTP2_HEADER_STATUS]
933
+
934
+ request.onRequestUpgrade(statusCode, headers, stream)
935
+
936
+ if (request.aborted || request.completed) {
937
+ return
938
+ }
939
+
940
+ removeUpgradeStreamListeners(stream)
941
+ detachRequestFromStream(request)
942
+ finalizeRequest(state)
943
+ }
944
+
945
+ function setupUpgradeStream (stream, state) {
946
+ const { request, headersTimeout, session } = state
947
+
948
+ stream[kHTTP2Stream] = true
949
+ stream[kHTTP2Session] = session
950
+ stream[kRequestStreamState] = state
951
+ state.stream = stream
952
+
953
+ bindRequestToStream(request, stream, releaseUpgradeStream)
954
+ stream.once('response', onUpgradeResponse)
955
+ stream.on('error', onUpgradeStreamError)
956
+ stream.once('end', onUpgradeStreamEnd)
957
+ stream.on('timeout', onUpgradeStreamTimeout)
958
+ stream.once('close', onUpgradeStreamClose)
959
+
960
+ clearHttp2IdleTimeout(session)
961
+ ++session[kOpenStreams]
962
+ stream.setTimeout(headersTimeout)
963
+ }
964
+
965
+ function finalizeRequest (state, resetPendingIdx = false) {
966
+ if (state.requestFinalized) {
967
+ return
968
+ }
969
+
970
+ state.requestFinalized = true
971
+ completeRequest(state.client, state.request, resetPendingIdx)
972
+
973
+ state.client[kResume]()
974
+ }
975
+
976
+ function openStream (client, request, session, abort, headers, options) {
977
+ try {
978
+ return session.request(headers, options)
979
+ } catch (err) {
980
+ // A GOAWAY'd session rejects new streams, same as an invalid session:
981
+ // reset and requeue on a fresh connection rather than the destroy + abort
982
+ // below, whose destroy(socket, err) can crash via an unhandled 'error'.
983
+ if (err?.code === 'ERR_HTTP2_INVALID_SESSION' || err?.code === 'ERR_HTTP2_GOAWAY_SESSION') {
984
+ const wrappedErr = new SocketError(err.message, util.getSocketInfo(session[kSocket]))
985
+ wrappedErr.cause = err
986
+ session[kError] = wrappedErr
987
+ resetHttp2Session(session, wrappedErr)
988
+ requeueUnsentRequest(client, request)
989
+
990
+ return null
991
+ }
992
+
993
+ const wrappedErr = new InformationalError(err.message, { cause: err })
994
+ session[kError] = wrappedErr
995
+ session[kSocket][kError] = wrappedErr
996
+
997
+ session.destroy(wrappedErr)
998
+ util.destroy(session[kSocket], wrappedErr)
999
+ abort(wrappedErr)
1000
+
1001
+ return null
1002
+ }
1003
+ }
1004
+
1005
+ function writeH2 (client, request) {
1006
+ const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout]
1007
+ const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout]
1008
+ const session = client[kHTTP2Session]
1009
+ const { method, path, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request
1010
+
1011
+ if (upgrade != null && upgrade !== 'websocket') {
1012
+ util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`))
1013
+ return false
1014
+ }
1015
+
1016
+ const headers = buildRequestHeaders(reqHeaders)
1017
+
1018
+ headers[HTTP2_HEADER_AUTHORITY] = host || client[kHostAuthority]
509
1019
  headers[HTTP2_HEADER_METHOD] = method
510
1020
 
511
- const abort = (err) => {
1021
+ // Single pre-shaped state object shared by all stream event handlers.
1022
+ // All fields are declared up-front so the object keeps a stable hidden
1023
+ // class for the whole request lifetime.
1024
+ const state = {
1025
+ abort: null,
1026
+ body: request.body,
1027
+ bytesRead: 0,
1028
+ client,
1029
+ contentLength: null,
1030
+ expectsPayload: false,
1031
+ maxResponseSize: client[kMaxResponseSize],
1032
+ request,
1033
+ headersTimeout,
1034
+ bodyTimeout,
1035
+ requestFinalized: false,
1036
+ responseReceived: false,
1037
+ bodySent: false,
1038
+ pendingEnd: false,
1039
+ trailers: null,
1040
+ session,
1041
+ stream: null
1042
+ }
1043
+
1044
+ const abort = (err, resetPendingIdx = false) => {
512
1045
  if (request.aborted || request.completed) {
513
1046
  return
514
1047
  }
@@ -517,29 +1050,44 @@ function writeH2 (client, request) {
517
1050
 
518
1051
  util.errorRequest(client, request, err)
519
1052
 
520
- if (stream != null) {
521
- // Some chunks might still come after abort,
522
- // let's ignore them
523
- stream.removeAllListeners('data')
1053
+ if (state.stream != null) {
1054
+ clearRequestStream(request)
524
1055
 
525
- // On Abort, we close the stream to send RST_STREAM frame
1056
+ // On Abort, we close the stream to send RST_STREAM frame.
1057
+ const stream = state.stream
526
1058
  stream.close()
527
1059
 
1060
+ // close() alone leaves cleanup waiting on the 'close' event; on a busy,
1061
+ // long-lived multiplexed session that event can fail to fire, leaving the
1062
+ // native Http2Stream (and the whole request graph it pins) alive for the
1063
+ // session's life. Destroy the stream synchronously to release the handle
1064
+ // deterministically. Deferring the destroy (e.g. via setImmediate) leaks
1065
+ // the same way when the event loop is stalled and the callback never runs
1066
+ // under abort churn (#5558); close() has already queued the RST_STREAM
1067
+ // frame on the native session, so a synchronous destroy still sends it.
1068
+ if (!stream.destroyed) {
1069
+ util.destroy(stream)
1070
+ }
1071
+
528
1072
  // We move the running index to the next request
529
1073
  client[kOnError](err)
530
- completeRequest(client, request)
531
- client[kResume]()
1074
+ finalizeRequest(state, resetPendingIdx)
532
1075
  }
533
1076
 
534
1077
  // We do not destroy the socket as we can continue using the session
535
1078
  // the stream gets destroyed and the session remains to create new streams
536
- util.destroy(body, err)
1079
+ util.destroy(state.body, err)
537
1080
  }
538
1081
 
1082
+ state.abort = abort
1083
+
1084
+ /** @type {import('node:http2').ClientHttp2Stream} */
1085
+ let stream = null
1086
+
539
1087
  try {
540
1088
  // We are already connected, streams are pending.
541
1089
  // We can call on connect, and wait for abort
542
- request.onConnect(abort)
1090
+ request.onRequestStart(abort, null)
543
1091
  } catch (err) {
544
1092
  util.errorRequest(client, request, err)
545
1093
  }
@@ -549,13 +1097,13 @@ function writeH2 (client, request) {
549
1097
  }
550
1098
 
551
1099
  if (upgrade || method === 'CONNECT') {
552
- session.ref()
1100
+ refH2Session(session)
553
1101
 
554
1102
  if (upgrade === 'websocket') {
555
1103
  // We cannot upgrade to websocket if extended CONNECT protocol is not supported
556
1104
  if (session[kEnableConnectProtocol] === false) {
557
1105
  util.errorRequest(client, request, new InformationalError('HTTP/2: Extended CONNECT protocol not supported by server'))
558
- session.unref()
1106
+ unrefH2Session(session)
559
1107
  return false
560
1108
  }
561
1109
 
@@ -573,33 +1121,12 @@ function writeH2 (client, request) {
573
1121
  headers[HTTP2_HEADER_SCHEME] = protocol === 'http:' ? 'http' : 'https'
574
1122
  }
575
1123
 
576
- stream = session.request(headers, { endStream: false, signal })
577
- stream[kHTTP2Stream] = true
578
-
579
- stream.once('response', (headers, _flags) => {
580
- const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
581
-
582
- request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream)
583
-
584
- ++session[kOpenStreams]
585
- completeRequest(client, request)
586
- })
587
-
588
- stream.on('error', () => {
589
- if (stream.rstCode === NGHTTP2_REFUSED_STREAM || stream.rstCode === NGHTTP2_CANCEL) {
590
- // NGHTTP2_REFUSED_STREAM (7) or NGHTTP2_CANCEL (8)
591
- // We do not treat those as errors as the server might
592
- // not support websockets and refuse the stream
593
- abort(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`))
594
- }
595
- })
596
-
597
- stream.once('close', () => {
598
- session[kOpenStreams] -= 1
599
- if (session[kOpenStreams] === 0) session.unref()
600
- })
601
-
602
- stream.setTimeout(headersTimeout)
1124
+ stream = openStream(client, request, session, abort, headers, { endStream: false, signal })
1125
+ if (stream == null) {
1126
+ unrefH2Session(session)
1127
+ return false
1128
+ }
1129
+ setupUpgradeStream(stream, state)
603
1130
  return true
604
1131
  }
605
1132
 
@@ -608,21 +1135,12 @@ function writeH2 (client, request) {
608
1135
  // will create a new stream. We trigger a request to create the stream and wait until
609
1136
  // `ready` event is triggered
610
1137
  // We disabled endStream to allow the user to write to the stream
611
- stream = session.request(headers, { endStream: false, signal })
612
- stream[kHTTP2Stream] = true
613
- stream.on('response', headers => {
614
- const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
615
-
616
- request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream)
617
- ++session[kOpenStreams]
618
- completeRequest(client, request)
619
- })
620
- stream.on('error', abort)
621
- stream.once('close', () => {
622
- session[kOpenStreams] -= 1
623
- if (session[kOpenStreams] === 0) session.unref()
624
- })
625
- stream.setTimeout(headersTimeout)
1138
+ stream = openStream(client, request, session, abort, headers, { endStream: false, signal })
1139
+ if (stream == null) {
1140
+ unrefH2Session(session)
1141
+ return false
1142
+ }
1143
+ setupUpgradeStream(stream, state)
626
1144
 
627
1145
  return true
628
1146
  }
@@ -644,9 +1162,14 @@ function writeH2 (client, request) {
644
1162
  const expectsPayload = (
645
1163
  method === 'PUT' ||
646
1164
  method === 'POST' ||
647
- method === 'PATCH'
1165
+ method === 'PATCH' ||
1166
+ method === 'QUERY' ||
1167
+ method === 'PROPFIND' ||
1168
+ method === 'PROPPATCH'
648
1169
  )
649
1170
 
1171
+ let body = state.body
1172
+
650
1173
  if (body && typeof body.read === 'function') {
651
1174
  // Try to read EOF in order to get length.
652
1175
  body.read(0)
@@ -668,7 +1191,7 @@ function writeH2 (client, request) {
668
1191
  contentLength = request.contentLength
669
1192
  }
670
1193
 
671
- if (!expectsPayload) {
1194
+ if (contentLength === 0 && !expectsPayload) {
672
1195
  // https://tools.ietf.org/html/rfc7230#section-3.3.2
673
1196
  // A user agent SHOULD NOT send a Content-Length header field when
674
1197
  // the request message does not contain a payload body and the method
@@ -693,7 +1216,7 @@ function writeH2 (client, request) {
693
1216
  headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`
694
1217
  }
695
1218
 
696
- session.ref()
1219
+ refH2Session(session)
697
1220
 
698
1221
  if (channels.sendHeaders.hasSubscribers) {
699
1222
  let header = ''
@@ -704,195 +1227,382 @@ function writeH2 (client, request) {
704
1227
  }
705
1228
 
706
1229
  // TODO(metcoder95): add support for sending trailers
707
- const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null
1230
+ const shouldEndStream = body === null || contentLength === 0
1231
+
1232
+ state.body = body
1233
+ state.contentLength = contentLength
1234
+ state.expectsPayload = expectsPayload
1235
+
708
1236
  if (expectContinue) {
709
1237
  headers[HTTP2_HEADER_EXPECT] = '100-continue'
710
- stream = session.request(headers, { endStream: shouldEndStream, signal })
711
- stream[kHTTP2Stream] = true
712
-
713
- stream.once('continue', writeBodyH2)
714
- } else {
715
- stream = session.request(headers, {
716
- endStream: shouldEndStream,
717
- signal
718
- })
719
- stream[kHTTP2Stream] = true
1238
+ }
720
1239
 
721
- writeBodyH2()
1240
+ stream = openStream(client, request, session, abort, headers, { endStream: shouldEndStream, signal })
1241
+ if (stream == null) {
1242
+ return false
722
1243
  }
1244
+ stream[kHTTP2Stream] = true
1245
+ stream[kRequestStreamState] = state
1246
+ state.stream = stream
723
1247
 
724
1248
  // Increment counter as we have new streams open
1249
+ clearHttp2IdleTimeout(session)
725
1250
  ++session[kOpenStreams]
726
- stream.setTimeout(headersTimeout)
727
1251
 
728
- // Track whether we received a response (headers)
729
- let responseReceived = false
730
-
731
- stream.once('response', headers => {
732
- const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
733
- request.onResponseStarted()
734
- responseReceived = true
735
- stream.setTimeout(bodyTimeout)
736
-
737
- // Due to the stream nature, it is possible we face a race condition
738
- // where the stream has been assigned, but the request has been aborted
739
- // the request remains in-flight and headers hasn't been received yet
740
- // for those scenarios, best effort is to destroy the stream immediately
741
- // as there's no value to keep it open.
742
- if (request.aborted) {
743
- stream.removeAllListeners('data')
744
- return
745
- }
1252
+ if (headersTimeout) {
1253
+ stream.setTimeout(headersTimeout)
1254
+ }
746
1255
 
747
- if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) {
748
- stream.pause()
749
- }
1256
+ stream[kHTTP2Session] = session
1257
+ stream.on('close', completeRequestStream)
750
1258
 
751
- stream.on('data', (chunk) => {
752
- if (request.aborted || request.completed) {
753
- return
754
- }
1259
+ bindRequestToStream(request, stream, releaseRequestStream)
1260
+ if (expectContinue) {
1261
+ stream.once('continue', writeBodyH2)
1262
+ }
1263
+ // The handlers below either remove themselves on first invocation or
1264
+ // become unreachable once the stream closes, so plain `on` avoids the
1265
+ // per-listener `once` wrapper allocation.
1266
+ stream.on('response', onResponse)
1267
+ stream.on('headers', onInterimResponse)
1268
+ stream.on('end', onEnd)
1269
+ stream.on('error', onError)
1270
+ stream.on('frameError', onFrameError)
1271
+ stream.on('aborted', onAborted)
1272
+ if (headersTimeout || bodyTimeout) {
1273
+ stream.on('timeout', onTimeout)
1274
+ }
1275
+ stream.on('trailers', onTrailers)
755
1276
 
756
- if (request.onData(chunk) === false) {
757
- stream.pause()
758
- }
759
- })
760
- })
1277
+ if (!expectContinue) {
1278
+ writeBodyH2.call(stream)
1279
+ }
761
1280
 
762
- stream.once('end', () => {
763
- stream.removeAllListeners('data')
764
- // If we received a response, this is a normal completion
765
- if (responseReceived) {
766
- if (!request.aborted && !request.completed) {
767
- request.onComplete({})
768
- }
1281
+ return true
1282
+ }
769
1283
 
770
- completeRequest(client, request)
771
- client[kResume]()
772
- } else {
773
- // Stream ended without receiving a response - this is an error
774
- // (e.g., server destroyed the stream before sending headers)
775
- abort(new InformationalError('HTTP/2: stream half-closed (remote)'))
776
- completeRequest(client, request, true)
777
- client[kResume]()
778
- }
779
- })
1284
+ function removeRequestStreamListeners (stream) {
1285
+ stream.off('error', noop)
1286
+ stream.off('continue', writeBodyH2)
1287
+ stream.off('response', onResponse)
1288
+ stream.off('headers', onInterimResponse)
1289
+ stream.off('end', onEnd)
1290
+ stream.off('error', onError)
1291
+ stream.off('frameError', onFrameError)
1292
+ stream.off('aborted', onAborted)
1293
+ stream.off('timeout', onTimeout)
1294
+ stream.off('trailers', onTrailers)
1295
+ stream.off('data', onData)
1296
+ }
780
1297
 
781
- stream.once('close', () => {
782
- stream.removeAllListeners('data')
783
- session[kOpenStreams] -= 1
784
- if (session[kOpenStreams] === 0) {
785
- session.unref()
786
- }
1298
+ function releaseRequestStream (stream) {
1299
+ if (stream == null) {
1300
+ return
1301
+ }
787
1302
 
788
- // A stream can close without ever emitting 'end' or 'error': a peer's
789
- // RST_STREAM(CANCEL) received before the response is reported by Node as a
790
- // bare 'close', and destroying the stream unenrolls its timeout, so no
791
- // 'timeout' follows either. Nothing else would ever settle this request.
792
- if (!request.aborted && !request.completed) {
793
- abort(new InformationalError('HTTP/2: stream closed before the response was complete'))
794
- }
795
- })
1303
+ const state = stream[kRequestStreamState]
1304
+ if (state == null) {
1305
+ return
1306
+ }
796
1307
 
797
- stream.once('error', function (err) {
798
- stream.removeAllListeners('data')
799
- abort(err)
800
- })
1308
+ const { request } = state
801
1309
 
802
- stream.once('frameError', (type, code) => {
803
- stream.removeAllListeners('data')
804
- abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
805
- })
1310
+ if (request[kRequestStream] === stream) {
1311
+ detachRequestFromStream(request)
1312
+ }
806
1313
 
807
- stream.on('aborted', () => {
808
- stream.removeAllListeners('data')
809
- })
1314
+ // A closed or destroyed stream cannot emit further events; leaving the
1315
+ // listeners in place saves the removal scans (they are collected with
1316
+ // the stream). All handlers bail out when the stream state is gone.
1317
+ if (!stream.destroyed && !stream.closed) {
1318
+ removeRequestStreamListeners(stream)
1319
+ stream.once('error', noop)
1320
+ }
1321
+ }
810
1322
 
811
- stream.on('timeout', () => {
812
- const err = responseReceived
813
- ? new BodyTimeoutError(`HTTP/2: "body timeout after ${bodyTimeout}"`)
814
- : new HeadersTimeoutError(`HTTP/2: "headers timeout after ${headersTimeout}"`)
815
- stream.removeAllListeners('data')
816
- session[kOpenStreams] -= 1
1323
+ function onData (chunk) {
1324
+ const stream = this
1325
+ const state = stream[kRequestStreamState]
817
1326
 
818
- if (session[kOpenStreams] === 0) {
819
- session.unref()
820
- }
1327
+ if (state == null) {
1328
+ return
1329
+ }
821
1330
 
822
- abort(err)
823
- })
1331
+ const { request, maxResponseSize } = state
824
1332
 
825
- stream.once('trailers', trailers => {
826
- if (request.aborted || request.completed) {
827
- return
1333
+ if (request.aborted || request.completed) {
1334
+ return
1335
+ }
1336
+
1337
+ if (maxResponseSize > -1 && state.bytesRead + chunk.length > maxResponseSize) {
1338
+ // Unlike HTTP/1.1, which destroys the socket because it cannot abandon one
1339
+ // response without losing framing, resetting the offending stream leaves
1340
+ // the session usable for its siblings.
1341
+ state.abort(new ResponseExceededMaxSizeError())
1342
+ return
1343
+ }
1344
+
1345
+ state.bytesRead += chunk.length
1346
+
1347
+ if (request.onResponseData(chunk) === false) {
1348
+ stream.pause()
1349
+ }
1350
+ }
1351
+
1352
+ function onInterimResponse (headers) {
1353
+ const stream = this
1354
+ const state = stream[kRequestStreamState]
1355
+
1356
+ if (state == null) {
1357
+ return
1358
+ }
1359
+
1360
+ const { request } = state
1361
+
1362
+ if (request.aborted || request.completed) {
1363
+ return
1364
+ }
1365
+
1366
+ // node http2 emits 'headers' for interim (1xx) informational responses,
1367
+ // while the final response arrives via 'response'. Forward these to the
1368
+ // handler so that onInfo is invoked, matching the HTTP/1 behaviour and the
1369
+ // documented onInfo contract.
1370
+ const statusCode = headers[HTTP2_HEADER_STATUS]
1371
+ delete headers[HTTP2_HEADER_STATUS]
1372
+
1373
+ request.onResponseStart(Number(statusCode), headers, noop, '')
1374
+ }
1375
+
1376
+ function onResponse (headers) {
1377
+ const stream = this
1378
+ const state = stream[kRequestStreamState]
1379
+
1380
+ if (state == null) {
1381
+ return
1382
+ }
1383
+
1384
+ const { request } = state
1385
+
1386
+ stream.off('response', onResponse)
1387
+
1388
+ // Final response received while still awaiting 100 (Continue): the body won't
1389
+ // be sent, so close our half or the stream stays open and never completes.
1390
+ if (state.body != null && !state.bodySent && !stream.writableEnded) {
1391
+ stream.removeListener('continue', writeBodyH2)
1392
+ stream.end()
1393
+ }
1394
+
1395
+ const statusCode = headers[HTTP2_HEADER_STATUS]
1396
+ delete headers[HTTP2_HEADER_STATUS]
1397
+ request.onResponseStarted()
1398
+ state.responseReceived = true
1399
+
1400
+ if (state.headersTimeout || state.bodyTimeout) {
1401
+ stream.setTimeout(state.bodyTimeout)
1402
+ }
1403
+
1404
+ // Due to the stream nature, it is possible we face a race condition
1405
+ // where the stream has been assigned, but the request has been aborted
1406
+ // or already completed and headers hasn't been received yet. A late
1407
+ // 'response' delivered after completion would call request.onResponseStart
1408
+ // post-completion, tripping its `assert(!this.completed)` (an uncatchable
1409
+ // throw on the http2 event tick). Guard `completed` here as onEnd/onTrailers
1410
+ // already do; best effort is to release the stream immediately as there's
1411
+ // no value to keep it open.
1412
+ if (request.aborted || request.completed) {
1413
+ releaseRequestStream(stream)
1414
+ return
1415
+ }
1416
+
1417
+ if (request.onResponseStart(Number(statusCode), headers, stream.resume.bind(stream), '') === false) {
1418
+ stream.pause()
1419
+ }
1420
+
1421
+ stream.on('data', onData)
1422
+ }
1423
+
1424
+ function onEnd () {
1425
+ const stream = this
1426
+ const state = stream[kRequestStreamState]
1427
+
1428
+ if (state == null) {
1429
+ return
1430
+ }
1431
+
1432
+ const { request } = state
1433
+
1434
+ stream.off('end', onEnd)
1435
+
1436
+ // onTrailers (which may fire after 'end' on Windows) has already stored
1437
+ // trailers on the state by now, so completing here still delivers them.
1438
+ if (state.responseReceived) {
1439
+ if (!request.aborted && !request.completed) {
1440
+ state.pendingEnd = true
1441
+
1442
+ // Complete on 'end': a blocked event loop can keep the stream's 'close'
1443
+ // from firing, stranding its buffers until OOM. Idempotent, so a later
1444
+ // 'close' no-ops.
1445
+ completeRequestStream.call(stream)
828
1446
  }
1447
+ } else {
1448
+ // Stream ended without receiving a response - this is an error
1449
+ // (e.g., server destroyed the stream before sending headers)
1450
+ state.abort(new InformationalError('HTTP/2: stream half-closed (remote)'), true)
1451
+ }
1452
+ }
829
1453
 
830
- stream.removeAllListeners('data')
831
- request.onComplete(trailers)
832
- })
1454
+ function retryRefusedStream (stream, state) {
1455
+ const { client, request } = state
1456
+
1457
+ if (
1458
+ state.responseReceived ||
1459
+ request.aborted ||
1460
+ request.completed ||
1461
+ request[kRefusedStreamRetry] ||
1462
+ !canReplayRequest(request)
1463
+ ) {
1464
+ return false
1465
+ }
1466
+
1467
+ // RFC 9113 section 8.7 permits retrying REFUSED_STREAM, but says clients
1468
+ // SHOULD NOT automatically retry the same request more than once.
1469
+ request[kRefusedStreamRetry] = true
1470
+
1471
+ // Detach the failed attempt before moving the request back to the pending
1472
+ // queue. The peer only reset this stream, so the HTTP/2 session remains
1473
+ // usable for the retry. Severing also drops the 'close' listener, so the
1474
+ // abandoned stream cannot later complete the retried request.
1475
+ detachRequestStreamForClose(request)
1476
+ state.stream = null
1477
+ state.requestFinalized = true
1478
+
1479
+ completeRequest(client, request)
1480
+ client[kQueue].splice(client[kPendingIdx], 0, request)
1481
+ client[kResume]()
833
1482
 
834
1483
  return true
1484
+ }
835
1485
 
836
- function writeBodyH2 () {
837
- if (!body || contentLength === 0) {
838
- writeBuffer(
839
- abort,
840
- stream,
841
- null,
842
- client,
843
- request,
844
- client[kSocket],
845
- contentLength,
846
- expectsPayload
847
- )
848
- } else if (util.isBuffer(body)) {
849
- writeBuffer(
1486
+ function onError (err) {
1487
+ const stream = this
1488
+ const state = stream[kRequestStreamState]
1489
+
1490
+ if (state == null) {
1491
+ return
1492
+ }
1493
+
1494
+ stream.off('error', onError)
1495
+
1496
+ if (typeof stream.rstCode === 'number' && stream.rstCode !== NGHTTP2_NO_ERROR) {
1497
+ err.http2ErrorCode = stream.rstCode
1498
+ }
1499
+
1500
+ if (
1501
+ stream.rstCode === NGHTTP2_REFUSED_STREAM &&
1502
+ retryRefusedStream(stream, state)
1503
+ ) {
1504
+ return
1505
+ }
1506
+
1507
+ state.abort(err)
1508
+ }
1509
+
1510
+ function onFrameError (type, code) {
1511
+ const stream = this
1512
+ const state = stream[kRequestStreamState]
1513
+
1514
+ if (state == null) {
1515
+ return
1516
+ }
1517
+
1518
+ stream.off('frameError', onFrameError)
1519
+ state.abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
1520
+ }
1521
+
1522
+ function onAborted () {
1523
+ this.off('data', onData)
1524
+ }
1525
+
1526
+ function onTimeout () {
1527
+ const stream = this
1528
+ const state = stream[kRequestStreamState]
1529
+
1530
+ if (state == null) {
1531
+ return
1532
+ }
1533
+
1534
+ // Remove self so timeout doesn't fire again after we handle it
1535
+ stream.off('timeout', onTimeout)
1536
+
1537
+ const err = state.responseReceived
1538
+ ? new BodyTimeoutError(`HTTP/2: "stream timeout after ${state.bodyTimeout}"`)
1539
+ : new HeadersTimeoutError(`HTTP/2: "headers timeout after ${state.headersTimeout}"`)
1540
+ state.abort(err)
1541
+ }
1542
+
1543
+ function onTrailers (trailers) {
1544
+ const stream = this
1545
+ const state = stream[kRequestStreamState]
1546
+
1547
+ if (state == null) {
1548
+ return
1549
+ }
1550
+
1551
+ const { request } = state
1552
+
1553
+ stream.off('trailers', onTrailers)
1554
+ stream.off('data', onData)
1555
+
1556
+ if (request.aborted || request.completed) {
1557
+ return
1558
+ }
1559
+
1560
+ // Store trailers for completeRequestStream to use when completing
1561
+ state.trailers = trailers
1562
+ }
1563
+
1564
+ function writeBodyH2 () {
1565
+ const stream = this
1566
+ const state = stream[kRequestStreamState]
1567
+ state.bodySent = true
1568
+ const { abort, body, client, contentLength, expectsPayload, request } = state
1569
+
1570
+ if (!body || contentLength === 0) {
1571
+ writeBuffer(
1572
+ abort,
1573
+ stream,
1574
+ null,
1575
+ client,
1576
+ request,
1577
+ client[kSocket],
1578
+ contentLength,
1579
+ expectsPayload
1580
+ )
1581
+ } else if (util.isBuffer(body)) {
1582
+ writeBuffer(
1583
+ abort,
1584
+ stream,
1585
+ body,
1586
+ client,
1587
+ request,
1588
+ client[kSocket],
1589
+ contentLength,
1590
+ expectsPayload
1591
+ )
1592
+ } else if (util.isBlobLike(body)) {
1593
+ if (typeof body.stream === 'function') {
1594
+ writeIterable(
850
1595
  abort,
851
1596
  stream,
852
- body,
1597
+ body.stream(),
853
1598
  client,
854
1599
  request,
855
1600
  client[kSocket],
856
1601
  contentLength,
857
1602
  expectsPayload
858
1603
  )
859
- } else if (util.isBlobLike(body)) {
860
- if (typeof body.stream === 'function') {
861
- writeIterable(
862
- abort,
863
- stream,
864
- body.stream(),
865
- client,
866
- request,
867
- client[kSocket],
868
- contentLength,
869
- expectsPayload
870
- )
871
- } else {
872
- writeBlob(
873
- abort,
874
- stream,
875
- body,
876
- client,
877
- request,
878
- client[kSocket],
879
- contentLength,
880
- expectsPayload
881
- )
882
- }
883
- } else if (util.isStream(body)) {
884
- writeStream(
885
- abort,
886
- client[kSocket],
887
- expectsPayload,
888
- stream,
889
- body,
890
- client,
891
- request,
892
- contentLength
893
- )
894
- } else if (util.isIterable(body)) {
895
- writeIterable(
1604
+ } else {
1605
+ writeBlob(
896
1606
  abort,
897
1607
  stream,
898
1608
  body,
@@ -902,9 +1612,31 @@ function writeH2 (client, request) {
902
1612
  contentLength,
903
1613
  expectsPayload
904
1614
  )
905
- } else {
906
- assert(false)
907
1615
  }
1616
+ } else if (util.isStream(body)) {
1617
+ writeStream(
1618
+ abort,
1619
+ client[kSocket],
1620
+ expectsPayload,
1621
+ stream,
1622
+ body,
1623
+ client,
1624
+ request,
1625
+ contentLength
1626
+ )
1627
+ } else if (util.isIterable(body)) {
1628
+ writeIterable(
1629
+ abort,
1630
+ stream,
1631
+ body,
1632
+ client,
1633
+ request,
1634
+ client[kSocket],
1635
+ contentLength,
1636
+ expectsPayload
1637
+ )
1638
+ } else {
1639
+ assert(false)
908
1640
  }
909
1641
  }
910
1642
 
@@ -963,8 +1695,6 @@ function writeStream (abort, socket, expectsPayload, h2stream, body, client, req
963
1695
  }
964
1696
 
965
1697
  async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) {
966
- assert(contentLength === body.size, 'blob body must have content length')
967
-
968
1698
  try {
969
1699
  if (contentLength != null && contentLength !== body.size) {
970
1700
  throw new RequestContentLengthMismatchError()