@openclaw/slack 2026.9.6 → 2026.9.8

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 (291) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{account-inspect-DP1Bcwj4.mjs → account-inspect-DWBXpER6.mjs} +1 -1
  3. package/dist/.setup/{accounts-BBHvg0pY.mjs → accounts-D_N9IqNA.mjs} +23 -1
  4. package/dist/.setup/{action-runtime-B01d85zt.mjs → action-runtime-DfWvuiZd.mjs} +26 -41
  5. package/dist/.setup/action-runtime.runtime-Ck4bAWOX.mjs +2 -0
  6. package/dist/.setup/{actions-DKCtBgCI.mjs → actions-Df0CzcDl.mjs} +88 -175
  7. package/dist/.setup/{approval-handler.runtime-DMszKn_7.mjs → approval-handler.runtime-Ed6Sw5VK.mjs} +37 -47
  8. package/dist/.setup/{approval-message-updates-Tb_qRokK.mjs → approval-message-updates-BadvtA7R.mjs} +1 -2
  9. package/dist/.setup/{channel-CErYZ5zw.mjs → channel-C7bgPSTE.mjs} +181 -273
  10. package/dist/.setup/channel-meta-C443t-lI.mjs +27 -0
  11. package/dist/.setup/{channel-type-Dxk8VJUb.mjs → channel-type-ClOttrZ5.mjs} +13 -21
  12. package/dist/.setup/{channel.setup-BVoUtdPn.mjs → channel.setup-Dh2jzAjN.mjs} +35 -42
  13. package/dist/.setup/{config-schema-CyL279e7.mjs → config-schema-BZCxmHKG.mjs} +24 -21
  14. package/dist/.setup/{directory-config-CQTSH45W.mjs → directory-config-BOUWH3hR.mjs} +7 -10
  15. package/dist/.setup/{directory-live-BCcj89QV.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-C0PTFaNV.mjs → message-tool-api-Cu4lwlGy.mjs} +34 -48
  18. package/dist/.setup/{provider-C-jPaGt2.mjs → monitor-BPVfkumU.mjs} +2181 -2693
  19. package/dist/.setup/{outbound-adapter-A7Wdn8ZT.mjs → outbound-adapter-Bv48XUjq.mjs} +10 -21
  20. package/dist/.setup/{pipeline.runtime-BlPOexmJ.mjs → pipeline.runtime-B1H63Frf.mjs} +311 -457
  21. package/dist/.setup/{plugin-routes-C3X0eVaK.mjs → plugin-routes-B8tooDLj.mjs} +1 -1
  22. package/dist/.setup/{policy-BApW53pI.mjs → policy-D-jfM174.mjs} +5 -5
  23. package/dist/.setup/{probe-DiYIMPJo.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-DfOnjJTE.mjs → relay-source-BpKdjsll.mjs} +10 -12
  26. package/dist/.setup/{replies-BBAJxUOQ.mjs → replies-BAnUtr2f.mjs} +16 -76
  27. package/dist/.setup/{reply-blocks-Bm8kf6mK.mjs → reply-blocks-SE1kTE3I.mjs} +27 -154
  28. package/dist/.setup/{resolve-channels-BXbMBbJD.mjs → resolve-channels-XXBn8UU_.mjs} +4 -5
  29. package/dist/.setup/{resolve-users-65WqvIqD.mjs → resolve-users-DW0ngD03.mjs} +20 -22
  30. package/dist/.setup/{scopes-h3YB-mMs.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-Cp6omkOg.mjs → send-BOVLQi3n.mjs} +84 -171
  35. package/dist/.setup/{session-status-Cf7AvWOt.mjs → session-status-DscajIsd.mjs} +315 -238
  36. package/dist/.setup/{setup-plugin-api-dLPkL06L.mjs → setup-plugin-api-DTtbTKNk.mjs} +1 -1
  37. package/dist/.setup/{setup-surface-D3DLcCxu.mjs → setup-surface-Dn7QgWRE.mjs} +24 -56
  38. package/dist/.setup/{shared-CJ3arAFL.mjs → shared-qau-uDGl.mjs} +30 -56
  39. package/dist/.setup/{slash-dispatch.runtime-HFy_XvyO.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/worker_threads.d.ts +4 -1
  73. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
  74. package/node_modules/@slack/web-api/node_modules/@types/node/child_process.d.ts +1 -1
  75. package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +20 -8
  76. package/node_modules/@slack/web-api/node_modules/@types/node/ffi.d.ts +14 -0
  77. package/node_modules/@slack/web-api/node_modules/@types/node/http2.d.ts +3 -2
  78. package/node_modules/@slack/web-api/node_modules/@types/node/net.d.ts +16 -4
  79. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
  80. package/node_modules/@slack/web-api/node_modules/@types/node/process.d.ts +1 -0
  81. package/node_modules/@slack/web-api/node_modules/@types/node/quic.d.ts +39 -1
  82. package/node_modules/@slack/web-api/node_modules/@types/node/stream/iter.d.ts +9 -12
  83. package/node_modules/@slack/web-api/node_modules/@types/node/test/reporters.d.ts +1 -0
  84. package/node_modules/@slack/web-api/node_modules/@types/node/test.d.ts +72 -0
  85. package/node_modules/@slack/web-api/node_modules/@types/node/tls.d.ts +14 -10
  86. package/node_modules/@slack/web-api/node_modules/@types/node/vm.d.ts +2 -1
  87. package/node_modules/@slack/web-api/node_modules/@types/node/worker_threads.d.ts +4 -1
  88. package/node_modules/get-east-asian-width/index.js +8 -3
  89. package/node_modules/get-east-asian-width/lookup-data.js +1 -1
  90. package/node_modules/get-east-asian-width/lookup.js +4 -4
  91. package/node_modules/get-east-asian-width/package.json +1 -1
  92. package/node_modules/typebox/build/compile/code.mjs +1 -2
  93. package/node_modules/typebox/build/compile/validator.mjs +5 -1
  94. package/node_modules/typebox/build/format/iri.mjs +16 -9
  95. package/node_modules/typebox/build/guard/emit.mjs +2 -2
  96. package/node_modules/typebox/build/guard/guard.d.mts +7 -5
  97. package/node_modules/typebox/build/guard/guard.mjs +14 -9
  98. package/node_modules/typebox/build/guard/index.mjs +6 -0
  99. package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
  100. package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
  101. package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
  102. package/node_modules/typebox/build/schema/build.mjs +2 -3
  103. package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
  104. package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
  105. package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
  106. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
  107. package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
  108. package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
  109. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
  110. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
  111. package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
  112. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
  113. package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
  114. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
  115. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
  116. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
  117. package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
  118. package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
  119. package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
  120. package/node_modules/typebox/build/schema/parse.mjs +3 -0
  121. package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
  122. package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
  123. package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
  124. package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
  125. package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
  126. package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
  127. package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
  128. package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
  129. package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
  130. package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
  131. package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
  132. package/node_modules/typebox/package.json +1 -1
  133. package/node_modules/typebox/readme.md +3 -1
  134. package/node_modules/undici/README.md +81 -25
  135. package/node_modules/undici/docs/docs/api/Agent.md +249 -42
  136. package/node_modules/undici/docs/docs/api/BalancedPool.md +246 -48
  137. package/node_modules/undici/docs/docs/api/CacheStorage.md +171 -13
  138. package/node_modules/undici/docs/docs/api/CacheStore.md +294 -98
  139. package/node_modules/undici/docs/docs/api/Client.md +407 -162
  140. package/node_modules/undici/docs/docs/api/ClientStats.md +80 -14
  141. package/node_modules/undici/docs/docs/api/Connector.md +118 -35
  142. package/node_modules/undici/docs/docs/api/ContentType.md +65 -25
  143. package/node_modules/undici/docs/docs/api/Cookies.md +122 -71
  144. package/node_modules/undici/docs/docs/api/Debug.md +34 -18
  145. package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +364 -164
  146. package/node_modules/undici/docs/docs/api/Dispatcher.md +490 -1055
  147. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +105 -93
  148. package/node_modules/undici/docs/docs/api/Errors.md +503 -28
  149. package/node_modules/undici/docs/docs/api/EventSource.md +326 -13
  150. package/node_modules/undici/docs/docs/api/Fetch.md +681 -30
  151. package/node_modules/undici/docs/docs/api/GlobalInstallation.md +78 -96
  152. package/node_modules/undici/docs/docs/api/H2CClient.md +298 -176
  153. package/node_modules/undici/docs/docs/api/Interceptors.md +418 -0
  154. package/node_modules/undici/docs/docs/api/MockAgent.md +333 -314
  155. package/node_modules/undici/docs/docs/api/MockCallHistory.md +272 -98
  156. package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +189 -26
  157. package/node_modules/undici/docs/docs/api/MockClient.md +151 -33
  158. package/node_modules/undici/docs/docs/api/MockErrors.md +56 -5
  159. package/node_modules/undici/docs/docs/api/MockPool.md +321 -258
  160. package/node_modules/undici/docs/docs/api/Pool.md +236 -41
  161. package/node_modules/undici/docs/docs/api/PoolStats.md +119 -13
  162. package/node_modules/undici/docs/docs/api/ProxyAgent.md +179 -160
  163. package/node_modules/undici/docs/docs/api/RedirectHandler.md +238 -55
  164. package/node_modules/undici/docs/docs/api/RetryAgent.md +113 -27
  165. package/node_modules/undici/docs/docs/api/RetryHandler.md +161 -79
  166. package/node_modules/undici/docs/docs/api/RoundRobinPool.md +166 -72
  167. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +262 -517
  168. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +177 -196
  169. package/node_modules/undici/docs/docs/api/Util.md +68 -11
  170. package/node_modules/undici/docs/docs/api/WebSocket.md +475 -80
  171. package/node_modules/undici/docs/docs/api/api-lifecycle.md +100 -32
  172. package/node_modules/undici/docs/docs/best-practices/client-certificate.md +2 -0
  173. package/node_modules/undici/docs/docs/best-practices/crawling.md +3 -1
  174. package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +233 -0
  175. package/node_modules/undici/docs/docs/best-practices/mocking-request.md +9 -7
  176. package/node_modules/undici/docs/docs/best-practices/proxy.md +3 -1
  177. package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +10 -8
  178. package/node_modules/undici/docs/docs/best-practices/writing-tests.md +2 -0
  179. package/node_modules/undici/docs/docs/getting-started.md +281 -0
  180. package/node_modules/undici/docs/docs/index.md +784 -0
  181. package/node_modules/undici/docs/docs/site.json +125 -0
  182. package/node_modules/undici/docs/docs/type-map.json +79 -0
  183. package/node_modules/undici/index.js +4 -2
  184. package/node_modules/undici/lib/api/api-connect.js +13 -11
  185. package/node_modules/undici/lib/api/api-pipeline.js +26 -13
  186. package/node_modules/undici/lib/api/api-request.js +51 -21
  187. package/node_modules/undici/lib/api/api-stream.js +81 -20
  188. package/node_modules/undici/lib/api/api-upgrade.js +21 -11
  189. package/node_modules/undici/lib/api/readable.js +45 -9
  190. package/node_modules/undici/lib/cache/memory-cache-store.js +3 -3
  191. package/node_modules/undici/lib/cache/sqlite-cache-store.js +3 -1
  192. package/node_modules/undici/lib/core/connect.js +46 -7
  193. package/node_modules/undici/lib/core/constants.js +1 -24
  194. package/node_modules/undici/lib/core/errors.js +22 -2
  195. package/node_modules/undici/lib/core/request.js +100 -18
  196. package/node_modules/undici/lib/core/symbols.js +4 -0
  197. package/node_modules/undici/lib/core/util.js +105 -48
  198. package/node_modules/undici/lib/dispatcher/agent.js +51 -32
  199. package/node_modules/undici/lib/dispatcher/balanced-pool.js +23 -27
  200. package/node_modules/undici/lib/dispatcher/client-h1.js +86 -24
  201. package/node_modules/undici/lib/dispatcher/client-h2.js +1091 -361
  202. package/node_modules/undici/lib/dispatcher/client.js +109 -36
  203. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +19 -6
  204. package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -5
  205. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +110 -0
  206. package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +37 -8
  207. package/node_modules/undici/lib/dispatcher/h2c-client.js +4 -4
  208. package/node_modules/undici/lib/dispatcher/pool-base.js +28 -10
  209. package/node_modules/undici/lib/dispatcher/pool.js +30 -5
  210. package/node_modules/undici/lib/dispatcher/proxy-agent.js +95 -19
  211. package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
  212. package/node_modules/undici/lib/dispatcher/round-robin-pool.js +32 -10
  213. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +153 -63
  214. package/node_modules/undici/lib/global.js +37 -14
  215. package/node_modules/undici/lib/handler/cache-handler.js +49 -7
  216. package/node_modules/undici/lib/handler/cache-revalidation-handler.js +10 -0
  217. package/node_modules/undici/lib/handler/decorator-handler.js +8 -3
  218. package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
  219. package/node_modules/undici/lib/handler/redirect-handler.js +66 -66
  220. package/node_modules/undici/lib/handler/retry-handler.js +191 -50
  221. package/node_modules/undici/lib/interceptor/cache.js +75 -25
  222. package/node_modules/undici/lib/interceptor/decompress.js +5 -2
  223. package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
  224. package/node_modules/undici/lib/interceptor/dns.js +12 -1
  225. package/node_modules/undici/lib/interceptor/redirect.js +3 -3
  226. package/node_modules/undici/lib/llhttp/llhttp-wasm.js +1 -1
  227. package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +1 -1
  228. package/node_modules/undici/lib/mock/mock-agent.js +21 -9
  229. package/node_modules/undici/lib/mock/mock-call-history.js +1 -1
  230. package/node_modules/undici/lib/mock/mock-interceptor.js +25 -7
  231. package/node_modules/undici/lib/mock/mock-utils.js +281 -47
  232. package/node_modules/undici/lib/mock/snapshot-agent.js +25 -7
  233. package/node_modules/undici/lib/mock/snapshot-recorder.js +38 -3
  234. package/node_modules/undici/lib/util/cache.js +92 -10
  235. package/node_modules/undici/lib/util/runtime-features.js +3 -34
  236. package/node_modules/undici/lib/web/cache/cache.js +6 -8
  237. package/node_modules/undici/lib/web/cookies/parse.js +150 -146
  238. package/node_modules/undici/lib/web/cookies/util.js +1 -1
  239. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
  240. package/node_modules/undici/lib/web/eventsource/eventsource.js +20 -21
  241. package/node_modules/undici/lib/web/eventsource/util.js +32 -1
  242. package/node_modules/undici/lib/web/fetch/body.js +48 -10
  243. package/node_modules/undici/lib/web/fetch/constants.js +1 -1
  244. package/node_modules/undici/lib/web/fetch/formdata.js +21 -2
  245. package/node_modules/undici/lib/web/fetch/index.js +242 -223
  246. package/node_modules/undici/lib/web/fetch/request.js +35 -6
  247. package/node_modules/undici/lib/web/fetch/response.js +1 -3
  248. package/node_modules/undici/lib/web/fetch/util.js +10 -2
  249. package/node_modules/undici/lib/web/webidl/index.js +5 -7
  250. package/node_modules/undici/lib/web/websocket/frame.js +1 -7
  251. package/node_modules/undici/lib/web/websocket/receiver.js +1 -1
  252. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +10 -10
  253. package/node_modules/undici/lib/web/websocket/websocket.js +25 -3
  254. package/node_modules/undici/package.json +10 -10
  255. package/node_modules/undici/types/agent.d.ts +0 -2
  256. package/node_modules/undici/types/client.d.ts +69 -24
  257. package/node_modules/undici/types/connector.d.ts +1 -0
  258. package/node_modules/undici/types/cookies.d.ts +1 -1
  259. package/node_modules/undici/types/dispatcher.d.ts +8 -30
  260. package/node_modules/undici/types/dispatcher1-wrapper.d.ts +7 -0
  261. package/node_modules/undici/types/errors.d.ts +10 -0
  262. package/node_modules/undici/types/fetch.d.ts +5 -1
  263. package/node_modules/undici/types/formdata.d.ts +0 -6
  264. package/node_modules/undici/types/h2c-client.d.ts +6 -6
  265. package/node_modules/undici/types/handlers.d.ts +2 -0
  266. package/node_modules/undici/types/header.d.ts +5 -0
  267. package/node_modules/undici/types/index.d.ts +3 -1
  268. package/node_modules/undici/types/interceptors.d.ts +1 -1
  269. package/node_modules/undici/types/mock-agent.d.ts +11 -10
  270. package/node_modules/undici/types/mock-interceptor.d.ts +5 -1
  271. package/node_modules/undici/types/pool.d.ts +0 -2
  272. package/node_modules/undici/types/proxy-agent.d.ts +9 -2
  273. package/node_modules/undici/types/round-robin-pool.d.ts +0 -2
  274. package/node_modules/undici/types/snapshot-agent.d.ts +4 -0
  275. package/node_modules/undici/types/socks5-proxy-agent.d.ts +4 -2
  276. package/node_modules/undici/types/webidl.d.ts +0 -1
  277. package/openclaw.plugin.json +31 -3
  278. package/package.json +7 -7
  279. package/dist/.setup/accounts.runtime-DN-PPocC.mjs +0 -2
  280. package/dist/.setup/action-runtime.runtime-C8R8CUan.mjs +0 -2
  281. package/dist/.setup/doctor-contract-CtMUqjvk.mjs +0 -186
  282. package/dist/.setup/monitor-_Sht7Dqy.mjs +0 -13
  283. package/dist/.setup/rolldown-runtime-D7D4PA-g.mjs +0 -13
  284. package/dist/.setup/send.runtime-B4caZU6T.mjs +0 -2
  285. package/dist/.setup/slash-commands.runtime-BpSH0b3q.mjs +0 -2
  286. package/dist/.setup/slash-skill-commands.runtime-Bi1JWZHY.mjs +0 -2
  287. package/node_modules/undici/lib/handler/unwrap-handler.js +0 -106
  288. package/node_modules/undici/lib/handler/wrap-handler.js +0 -105
  289. package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  290. package/node_modules/undici/lib/util/promise.js +0 -28
  291. /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
@@ -1,616 +1,361 @@
1
1
  # SnapshotAgent
2
2
 
3
- The `SnapshotAgent` provides a powerful way to record and replay HTTP requests for testing purposes. It extends `MockAgent` to enable automatic snapshot testing, eliminating the need to manually define mock responses.
3
+ <!--introduced_in=v7.13.0-->
4
+ <!--type=module-->
5
+ <!-- source_link=lib/mock/snapshot-agent.js -->
4
6
 
5
- ## Use Cases
7
+ > Stability: 1 - Experimental
6
8
 
7
- - **Integration Testing**: Record real API interactions and replay them in tests
8
- - **Offline Development**: Work with APIs without network connectivity
9
- - **Consistent Test Data**: Ensure tests use the same responses across runs
10
- - **API Contract Testing**: Capture and validate API behavior over time
9
+ `SnapshotAgent` records real HTTP responses and replays them on later requests,
10
+ allowing tests to run against deterministic, captured data instead of a live
11
+ network. It extends [`MockAgent`][], so it can be installed with
12
+ [`setGlobalDispatcher()`][] or passed explicitly through the `dispatcher`
13
+ option, and it works with every undici API (`fetch`, `request`, `stream`,
14
+ `pipeline`, and so on).
11
15
 
12
- ## Constructor
16
+ A `SnapshotAgent` operates in one of three modes. In `'record'` mode it performs
17
+ real requests and writes the responses to a snapshot file. In `'playback'` mode
18
+ it serves responses from the snapshot file without touching the network. In
19
+ `'update'` mode it replays existing snapshots and records any request that has no
20
+ matching snapshot.
13
21
 
14
- ```javascript
15
- new SnapshotAgent([options])
16
- ```
17
-
18
- ### Parameters
19
-
20
- - **options** `Object` (optional)
21
- - **mode** `String` - The snapshot mode: `'record'`, `'playback'`, or `'update'`. Default: `'record'`
22
- - **snapshotPath** `String` - Path to the snapshot file for loading/saving
23
- - **maxSnapshots** `Number` - Maximum number of snapshots to keep in memory. Default: `Infinity`
24
- - **autoFlush** `Boolean` - Whether to automatically save snapshots to disk. Default: `false`
25
- - **flushInterval** `Number` - Interval in milliseconds for auto-flush. Default: `30000`
26
- - **matchHeaders** `Array<String>` - Specific headers to include in request matching. Default: all headers
27
- - **ignoreHeaders** `Array<String>` - Headers to ignore during request matching
28
- - **excludeHeaders** `Array<String>` - Headers to exclude from snapshots (for security)
29
- - **matchBody** `Boolean` - Whether to include request body in matching. Default: `true`
30
- - **matchQuery** `Boolean` - Whether to include query parameters in matching. Default: `true`
31
- - **caseSensitive** `Boolean` - Whether header matching is case-sensitive. Default: `false`
32
- - **shouldRecord** `Function` - Callback to determine if a request should be recorded
33
- - **shouldPlayback** `Function` - Callback to determine if a request should be played back
34
- - **excludeUrls** `Array` - URL patterns (strings or RegExp) to exclude from recording/playback
35
- - All other options from `MockAgent` are supported
36
-
37
- ### Modes
38
-
39
- #### Record Mode (`'record'`)
40
- Makes real HTTP requests and saves the responses to snapshots.
41
-
42
- ```javascript
43
- import { SnapshotAgent, setGlobalDispatcher } from 'undici'
22
+ ```mjs
23
+ import { SnapshotAgent, setGlobalDispatcher, fetch } from 'undici'
44
24
 
45
- const agent = new SnapshotAgent({
25
+ const agent = new SnapshotAgent({
46
26
  mode: 'record',
47
- snapshotPath: './test/snapshots/api-calls.json'
27
+ snapshotPath: './snapshots/api.json'
48
28
  })
49
29
  setGlobalDispatcher(agent)
50
30
 
51
- // Makes real requests and records them
52
31
  const response = await fetch('https://api.example.com/users')
53
32
  const users = await response.json()
54
33
 
55
- // Save recorded snapshots
56
- await agent.saveSnapshots()
34
+ await agent.close()
57
35
  ```
58
36
 
59
- #### Playback Mode (`'playback'`)
60
- Replays recorded responses without making real HTTP requests.
61
-
62
- ```javascript
37
+ Constructing a `SnapshotAgent` emits an `ExperimentalWarning` once per process.
38
+
39
+ ## Class: `SnapshotAgent`
40
+
41
+ <!-- YAML
42
+ added: v7.13.0
43
+ -->
44
+
45
+ * Extends: {MockAgent}
46
+
47
+ The captured interactions are managed by an internal `SnapshotRecorder`, which
48
+ is accessible through [`agent.getRecorder()`][]. Because `SnapshotAgent` extends
49
+ [`MockAgent`][], all `MockAgent` and [`Dispatcher`][] methods and events are also
50
+ available.
51
+
52
+ ### `new SnapshotAgent([options])`
53
+
54
+ <!-- YAML
55
+ added: v7.13.0
56
+ -->
57
+
58
+ * `options` {Object} (optional) Accepts all [`MockAgent`][] options plus the
59
+ following snapshot-specific options.
60
+ * `mode` {string} The snapshot mode. One of `'record'`, `'playback'`, or
61
+ `'update'`. **Default:** `'record'`.
62
+ * `snapshotPath` {string} Path to the snapshot file used for loading and
63
+ saving. Required when `mode` is `'playback'` or `'update'`. **Default:**
64
+ `null`.
65
+ * `maxSnapshots` {number} Maximum number of snapshots to keep in memory.
66
+ **Default:** `Infinity`.
67
+ * `autoFlush` {boolean} When `true`, snapshots are written to `snapshotPath`
68
+ automatically as they are recorded. **Default:** `false`.
69
+ * `flushInterval` {number} Interval, in milliseconds, between automatic flushes
70
+ when `autoFlush` is enabled. **Default:** `30000`.
71
+ * `matchHeaders` {string[]} Names of the only headers to include when matching
72
+ a request against a snapshot. When omitted, all headers are matched.
73
+ * `ignoreHeaders` {string[]} Header names to ignore when matching a request.
74
+ * `excludeHeaders` {string[]} Header names to strip from snapshots entirely,
75
+ so that sensitive values are never written to disk.
76
+ * `matchBody` {boolean} When `true`, the request body is included in request
77
+ matching. **Default:** `true`.
78
+ * `normalizeBody` {Function} Normalizes the request body before it is matched
79
+ or stored, for example to strip volatile fields such as timestamps. Only
80
+ applied when `matchBody` is `true`.
81
+ * `body` {string|Buffer|null|undefined} The raw request body.
82
+ * Returns: {string} The normalized body used for matching.
83
+ * `matchQuery` {boolean} When `true`, query parameters are included in request
84
+ matching. **Default:** `true`.
85
+ * `normalizeQuery` {Function} Normalizes the query string before it is matched,
86
+ for example to strip cache-busting parameters. Only applied when `matchQuery`
87
+ is `true`.
88
+ * `query` {URLSearchParams} The parsed query parameters.
89
+ * Returns: {string} The normalized query string used for matching.
90
+ * `caseSensitive` {boolean} When `true`, header matching is case-sensitive.
91
+ **Default:** `false`.
92
+ * `shouldRecord` {Function} Decides whether a given request is recorded. Only
93
+ used in `'record'` and `'update'` modes.
94
+ * `requestOpts` {Object} The dispatch options of the request.
95
+ * Returns: {boolean} `true` to record the request.
96
+ * `shouldPlayback` {Function} Decides whether a given request is served from a
97
+ snapshot. Only used in `'playback'` and `'update'` modes.
98
+ * `requestOpts` {Object} The dispatch options of the request.
99
+ * Returns: {boolean} `true` to play the request back from a snapshot.
100
+ * `excludeUrls` {Array<string|RegExp>} URL patterns that are excluded from
101
+ recording and playback. String patterns match case-insensitively as
102
+ substrings of the URL; `RegExp` patterns are tested against the URL. Matching
103
+ requests are passed through to a real [`Agent`][] instead.
104
+
105
+ Creates a new `SnapshotAgent`. Throws an [`InvalidArgumentError`][] when `mode`
106
+ is `'playback'` or `'update'` and `snapshotPath` is not provided, and throws an
107
+ `InvalidArgumentError` when `mode` is not one of the supported values.
108
+
109
+ When `mode` is `'playback'` or `'update'` and `snapshotPath` is set, snapshots
110
+ are loaded from the file automatically; a missing file is ignored until the first
111
+ request requires it.
112
+
113
+ ```mjs
63
114
  import { SnapshotAgent, setGlobalDispatcher } from 'undici'
64
115
 
65
116
  const agent = new SnapshotAgent({
66
117
  mode: 'playback',
67
- snapshotPath: './test/snapshots/api-calls.json'
68
- })
69
- setGlobalDispatcher(agent)
70
-
71
- // Uses recorded response instead of real request
72
- const response = await fetch('https://api.example.com/users')
73
- ```
74
-
75
- #### Update Mode (`'update'`)
76
- Uses existing snapshots when available, but records new ones for missing requests.
77
-
78
- ```javascript
79
- import { SnapshotAgent, setGlobalDispatcher } from 'undici'
80
-
81
- const agent = new SnapshotAgent({
82
- mode: 'update',
83
- snapshotPath: './test/snapshots/api-calls.json'
118
+ snapshotPath: './snapshots/api.json'
84
119
  })
85
120
  setGlobalDispatcher(agent)
86
-
87
- // Uses snapshot if exists, otherwise makes real request and records it
88
- const response = await fetch('https://api.example.com/new-endpoint')
89
- ```
90
-
91
- ## Instance Methods
92
-
93
- ### `agent.saveSnapshots([filePath])`
94
-
95
- Saves all recorded snapshots to a file.
96
-
97
- #### Parameters
98
-
99
- - **filePath** `String` (optional) - Path to save snapshots. Uses constructor `snapshotPath` if not provided.
100
-
101
- #### Returns
102
-
103
- `Promise<void>`
104
-
105
- ```javascript
106
- await agent.saveSnapshots('./custom-snapshots.json')
107
- ```
108
-
109
- ## Advanced Configuration
110
-
111
- ### Header Filtering
112
-
113
- Control which headers are used for request matching and what gets stored in snapshots:
114
-
115
- ```javascript
116
- const agent = new SnapshotAgent({
117
- mode: 'record',
118
- snapshotPath: './snapshots.json',
119
-
120
- // Only match these specific headers
121
- matchHeaders: ['content-type', 'accept'],
122
-
123
- // Ignore these headers during matching (but still store them)
124
- ignoreHeaders: ['user-agent', 'date'],
125
-
126
- // Exclude sensitive headers from snapshots entirely
127
- excludeHeaders: ['authorization', 'x-api-key', 'cookie']
128
- })
129
- ```
130
-
131
- ### Custom Request/Response Filtering
132
-
133
- Use callback functions to determine what gets recorded or played back:
134
-
135
- ```javascript
136
- const agent = new SnapshotAgent({
137
- mode: 'record',
138
- snapshotPath: './snapshots.json',
139
-
140
- // Only record GET requests to specific endpoints
141
- shouldRecord: (requestOpts) => {
142
- const url = new URL(requestOpts.path, requestOpts.origin)
143
- return requestOpts.method === 'GET' && url.pathname.startsWith('/api/v1/')
144
- },
145
-
146
- // Skip authentication endpoints during playback
147
- shouldPlayback: (requestOpts) => {
148
- const url = new URL(requestOpts.path, requestOpts.origin)
149
- return !url.pathname.includes('/auth/')
150
- }
151
- })
152
- ```
153
-
154
- ### URL Pattern Exclusion
155
-
156
- Exclude specific URLs from recording/playback using patterns:
157
-
158
- ```javascript
159
- const agent = new SnapshotAgent({
160
- mode: 'record',
161
- snapshotPath: './snapshots.json',
162
-
163
- excludeUrls: [
164
- 'https://analytics.example.com', // String match
165
- /\/api\/v\d+\/health/, // Regex pattern
166
- 'telemetry' // Substring match
167
- ]
168
- })
169
121
  ```
170
122
 
171
- ### Memory Management
172
-
173
- Configure automatic memory and disk management:
174
-
175
- ```javascript
176
- const agent = new SnapshotAgent({
177
- mode: 'record',
178
- snapshotPath: './snapshots.json',
179
-
180
- // Keep only 1000 snapshots in memory
181
- maxSnapshots: 1000,
182
-
183
- // Automatically save to disk every 30 seconds
184
- autoFlush: true,
185
- flushInterval: 30000
186
- })
187
- ```
123
+ The mode controls how requests are handled:
188
124
 
189
- ### Sequential Response Handling
125
+ * `'record'` performs the real request and stores the response.
190
126
 
191
- Handle multiple responses for the same request (similar to nock):
127
+ ```mjs
128
+ import { SnapshotAgent, setGlobalDispatcher, fetch } from 'undici'
192
129
 
193
- ```javascript
194
- // In record mode, multiple identical requests get recorded as separate responses
195
- const agent = new SnapshotAgent({ mode: 'record', snapshotPath: './sequential.json' })
130
+ const agent = new SnapshotAgent({
131
+ mode: 'record',
132
+ snapshotPath: './snapshots/api.json'
133
+ })
134
+ setGlobalDispatcher(agent)
196
135
 
197
- // First call returns response A
198
- await fetch('https://api.example.com/random')
136
+ await fetch('https://api.example.com/users')
137
+ await agent.saveSnapshots()
138
+ ```
199
139
 
200
- // Second call returns response B
201
- await fetch('https://api.example.com/random')
140
+ * `'playback'` serves the recorded response without any network access. A
141
+ request with no matching snapshot rejects with an [`UndiciError`][] whose
142
+ message begins with `No snapshot found`.
202
143
 
203
- await agent.saveSnapshots()
144
+ ```mjs
145
+ import { SnapshotAgent, setGlobalDispatcher, fetch } from 'undici'
204
146
 
205
- // In playback mode, calls return responses in sequence
206
- const playbackAgent = new SnapshotAgent({ mode: 'playback', snapshotPath: './sequential.json' })
147
+ const agent = new SnapshotAgent({
148
+ mode: 'playback',
149
+ snapshotPath: './snapshots/api.json'
150
+ })
151
+ setGlobalDispatcher(agent)
207
152
 
208
- // Returns response A
209
- const first = await fetch('https://api.example.com/random')
153
+ const response = await fetch('https://api.example.com/users')
154
+ ```
210
155
 
211
- // Returns response B
212
- const second = await fetch('https://api.example.com/random')
156
+ * `'update'` replays an existing snapshot when one is found and otherwise records
157
+ the request like `'record'` mode.
213
158
 
214
- // Third call repeats the last response (B)
215
- const third = await fetch('https://api.example.com/random')
216
- ```
159
+ ```mjs
160
+ import { SnapshotAgent, setGlobalDispatcher, fetch } from 'undici'
217
161
 
218
- ## Managing Snapshots
162
+ const agent = new SnapshotAgent({
163
+ mode: 'update',
164
+ snapshotPath: './snapshots/api.json'
165
+ })
166
+ setGlobalDispatcher(agent)
219
167
 
220
- ### Replacing Existing Snapshots
168
+ await fetch('https://api.example.com/new-endpoint')
169
+ ```
221
170
 
222
- ```javascript
223
- // Load existing snapshots
224
- await agent.loadSnapshots('./old-snapshots.json')
171
+ ### `agent.loadSnapshots([filePath])`
225
172
 
226
- // Get snapshot data
227
- const recorder = agent.getRecorder()
228
- const snapshots = recorder.getSnapshots()
173
+ <!-- YAML
174
+ added: v7.13.0
175
+ -->
229
176
 
230
- // Modify or filter snapshots
231
- const filteredSnapshots = snapshots.filter(s =>
232
- !s.request.url.includes('deprecated')
233
- )
177
+ * `filePath` {string} (optional) Path to read snapshots from. **Default:** the
178
+ `snapshotPath` given to the constructor.
179
+ * Returns: {Promise<void>} Resolves when the snapshots have been loaded.
234
180
 
235
- // Replace all snapshots
236
- agent.replaceSnapshots(filteredSnapshots.map((snapshot, index) => ({
237
- hash: `new-hash-${index}`,
238
- snapshot
239
- })))
181
+ Loads snapshots from disk into memory. In `'playback'` mode this also installs
182
+ the corresponding [`MockAgent`][] interceptors so that subsequent requests are
183
+ matched against the loaded snapshots.
240
184
 
241
- // Save updated snapshots
242
- await agent.saveSnapshots('./updated-snapshots.json')
185
+ ```mjs
186
+ await agent.loadSnapshots('./snapshots/api.json')
243
187
  ```
244
188
 
245
- ### `agent.loadSnapshots([filePath])`
246
-
247
- Loads snapshots from a file.
248
-
249
- #### Parameters
189
+ ### `agent.saveSnapshots([filePath])`
250
190
 
251
- - **filePath** `String` (optional) - Path to load snapshots from. Uses constructor `snapshotPath` if not provided.
191
+ <!-- YAML
192
+ added: v7.13.0
193
+ -->
252
194
 
253
- #### Returns
195
+ * `filePath` {string} (optional) Path to write snapshots to. **Default:** the
196
+ `snapshotPath` given to the constructor.
197
+ * Returns: {Promise<void>} Resolves when the snapshots have been written.
254
198
 
255
- `Promise<void>`
199
+ Writes all recorded snapshots to disk.
256
200
 
257
- ```javascript
258
- await agent.loadSnapshots('./existing-snapshots.json')
201
+ ```mjs
202
+ await agent.saveSnapshots('./snapshots/api.json')
259
203
  ```
260
204
 
261
205
  ### `agent.getRecorder()`
262
206
 
263
- Gets the underlying `SnapshotRecorder` instance.
207
+ <!-- YAML
208
+ added: v7.13.0
209
+ -->
264
210
 
265
- #### Returns
211
+ * Returns: {SnapshotRecorder} The internal recorder that stores the captured
212
+ interactions.
266
213
 
267
- `SnapshotRecorder`
214
+ Returns the underlying `SnapshotRecorder`. The recorder exposes lower-level
215
+ operations over the captured data, including `record()`, `findSnapshot()`,
216
+ `getSnapshots()`, `size()`, and `clear()`. The recorder is an internal type
217
+ returned for inspection; it is not exported from the package root.
268
218
 
269
- ```javascript
219
+ ```mjs
270
220
  const recorder = agent.getRecorder()
271
221
  console.log(`Recorded ${recorder.size()} interactions`)
272
222
  ```
273
223
 
274
224
  ### `agent.getMode()`
275
225
 
276
- Gets the current snapshot mode.
226
+ <!-- YAML
227
+ added: v7.13.0
228
+ -->
277
229
 
278
- #### Returns
230
+ * Returns: {string} The current mode: `'record'`, `'playback'`, or `'update'`.
279
231
 
280
- `String` - The current mode (`'record'`, `'playback'`, or `'update'`)
232
+ Returns the mode the agent was constructed with.
281
233
 
282
234
  ### `agent.clearSnapshots()`
283
235
 
284
- Clears all recorded snapshots from memory.
236
+ <!-- YAML
237
+ added: v7.13.0
238
+ -->
285
239
 
286
- ```javascript
287
- agent.clearSnapshots()
288
- ```
289
-
290
- ## Working with Different Request Types
240
+ * Returns: {undefined}
291
241
 
292
- ### GET Requests
293
-
294
- ```javascript
295
- // Record mode
296
- const agent = new SnapshotAgent({ mode: 'record', snapshotPath: './get-snapshots.json' })
297
- setGlobalDispatcher(agent)
242
+ Removes all snapshots from memory.
298
243
 
299
- const response = await fetch('https://jsonplaceholder.typicode.com/posts/1')
300
- const post = await response.json()
301
-
302
- await agent.saveSnapshots()
303
- ```
304
-
305
- ### POST Requests with Body
306
-
307
- ```javascript
308
- // Record mode
309
- const agent = new SnapshotAgent({ mode: 'record', snapshotPath: './post-snapshots.json' })
310
- setGlobalDispatcher(agent)
311
-
312
- const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
313
- method: 'POST',
314
- headers: { 'Content-Type': 'application/json' },
315
- body: JSON.stringify({ title: 'Test Post', body: 'Content' })
316
- })
317
-
318
- await agent.saveSnapshots()
244
+ ```mjs
245
+ agent.clearSnapshots()
319
246
  ```
320
247
 
321
- ### Using with `undici.request`
322
-
323
- SnapshotAgent works with all undici APIs, not just fetch:
248
+ ### `agent.resetCallCounts()`
324
249
 
325
- ```javascript
326
- import { SnapshotAgent, request, setGlobalDispatcher } from 'undici'
250
+ <!-- YAML
251
+ added: v7.13.0
252
+ -->
327
253
 
328
- const agent = new SnapshotAgent({ mode: 'record', snapshotPath: './request-snapshots.json' })
329
- setGlobalDispatcher(agent)
330
-
331
- const { statusCode, headers, body } = await request('https://api.example.com/data')
332
- const data = await body.json()
333
-
334
- await agent.saveSnapshots()
335
- ```
336
-
337
- ## Test Integration
254
+ * Returns: {undefined}
338
255
 
339
- ### Basic Test Setup
256
+ Resets the call count of every snapshot to zero. Useful between tests when the
257
+ same agent is reused, since matching a snapshot in `'playback'` mode increments
258
+ its call count.
340
259
 
341
- ```javascript
342
- import { test } from 'node:test'
343
- import { SnapshotAgent, setGlobalDispatcher, getGlobalDispatcher } from 'undici'
344
-
345
- test('API integration test', async (t) => {
346
- const originalDispatcher = getGlobalDispatcher()
347
-
348
- const agent = new SnapshotAgent({
349
- mode: 'playback',
350
- snapshotPath: './test/snapshots/api-test.json'
351
- })
352
- setGlobalDispatcher(agent)
353
-
354
- t.after(() => setGlobalDispatcher(originalDispatcher))
355
-
356
- // This will use recorded data
357
- const response = await fetch('https://api.example.com/users')
358
- const users = await response.json()
359
-
360
- assert(Array.isArray(users))
361
- assert(users.length > 0)
362
- })
260
+ ```mjs
261
+ agent.resetCallCounts()
363
262
  ```
364
263
 
365
- ### Environment-Based Mode Selection
366
-
367
- ```javascript
368
- const mode = process.env.SNAPSHOT_MODE || 'playback'
369
-
370
- const agent = new SnapshotAgent({
371
- mode,
372
- snapshotPath: './test/snapshots/integration.json'
373
- })
264
+ ### `agent.deleteSnapshot(requestOpts)`
374
265
 
375
- // Run with: SNAPSHOT_MODE=record npm test (to record)
376
- // Run with: npm test (to playback)
377
- ```
266
+ <!-- YAML
267
+ added: v7.13.0
268
+ -->
378
269
 
379
- ### Test Helper Function
270
+ * `requestOpts` {Object} Dispatch options identifying the snapshot to remove.
271
+ * Returns: {boolean} `true` if a matching snapshot was deleted, `false` if none
272
+ was found.
380
273
 
381
- ```javascript
382
- function createSnapshotAgent(testName, mode = 'playback') {
383
- return new SnapshotAgent({
384
- mode,
385
- snapshotPath: `./test/snapshots/${testName}.json`
386
- })
387
- }
274
+ Deletes a single snapshot that matches the given request options.
388
275
 
389
- test('user API test', async (t) => {
390
- const agent = createSnapshotAgent('user-api')
391
- setGlobalDispatcher(agent)
392
-
393
- // Test implementation...
276
+ ```mjs
277
+ const deleted = agent.deleteSnapshot({
278
+ method: 'GET',
279
+ origin: 'https://api.example.com',
280
+ path: '/users'
394
281
  })
395
282
  ```
396
283
 
397
- ## Snapshot File Format
398
-
399
- Snapshots are stored as JSON with the following structure:
400
-
401
- ```json
402
- [
403
- {
404
- "hash": "dGVzdC1oYXNo...",
405
- "snapshot": {
406
- "request": {
407
- "method": "GET",
408
- "url": "https://api.example.com/users",
409
- "headers": {
410
- "authorization": "Bearer token"
411
- },
412
- "body": undefined
413
- },
414
- "response": {
415
- "statusCode": 200,
416
- "headers": {
417
- "content-type": "application/json"
418
- },
419
- "body": "eyJkYXRhIjoidGVzdCJ9", // base64 encoded
420
- "trailers": {}
421
- },
422
- "timestamp": "2024-01-01T00:00:00.000Z"
423
- }
424
- }
425
- ]
426
- ```
427
-
428
- ## Security Considerations
429
-
430
- ### Sensitive Data in Snapshots
431
-
432
- By default, SnapshotAgent records all headers and request/response data. For production use, always exclude sensitive information:
433
-
434
- ```javascript
435
- const agent = new SnapshotAgent({
436
- mode: 'record',
437
- snapshotPath: './snapshots.json',
438
-
439
- // Exclude sensitive headers from snapshots
440
- excludeHeaders: [
441
- 'authorization',
442
- 'x-api-key',
443
- 'cookie',
444
- 'set-cookie',
445
- 'x-auth-token',
446
- 'x-csrf-token'
447
- ],
448
-
449
- // Filter out requests with sensitive data
450
- shouldRecord: (requestOpts) => {
451
- const url = new URL(requestOpts.path, requestOpts.origin)
452
-
453
- // Don't record authentication endpoints
454
- if (url.pathname.includes('/auth/') || url.pathname.includes('/login')) {
455
- return false
456
- }
457
-
458
- // Don't record if request contains sensitive body data
459
- if (requestOpts.body && typeof requestOpts.body === 'string') {
460
- const body = requestOpts.body.toLowerCase()
461
- if (body.includes('password') || body.includes('secret')) {
462
- return false
463
- }
464
- }
465
-
466
- return true
467
- }
284
+ ### `agent.getSnapshotInfo(requestOpts)`
285
+
286
+ <!-- YAML
287
+ added: v7.13.0
288
+ -->
289
+
290
+ * `requestOpts` {Object} Dispatch options identifying the snapshot to inspect.
291
+ * Returns: {Object|null} Information about the matching snapshot, or `null` when
292
+ none is found.
293
+ * `hash` {string} The hash used to key the snapshot.
294
+ * `request` {Object} The recorded request.
295
+ * `method` {string} The request method.
296
+ * `url` {string} The request URL.
297
+ * `headers` {Record<string, string>} The recorded request headers.
298
+ * `body` {string} The recorded request body, when present.
299
+ * `responseCount` {number} The number of recorded responses for the request.
300
+ * `callCount` {number} The number of times the snapshot has been matched.
301
+ * `timestamp` {string} The ISO timestamp at which the snapshot was recorded.
302
+
303
+ Returns metadata about a snapshot without returning the response payload.
304
+
305
+ ```mjs
306
+ const info = agent.getSnapshotInfo({
307
+ method: 'GET',
308
+ origin: 'https://api.example.com',
309
+ path: '/users'
468
310
  })
469
311
  ```
470
312
 
471
- ### Snapshot File Security
472
-
473
- **Important**: Snapshot files may contain sensitive data. Handle them securely:
474
-
475
- - ✅ Add snapshot files to `.gitignore` if they contain real API data
476
- - ✅ Use environment-specific snapshots (dev/staging/prod)
477
- - ✅ Regularly review snapshot contents for sensitive information
478
- - ✅ Use the `excludeHeaders` option for production snapshots
479
- - ❌ Never commit snapshots with real authentication tokens
480
- - ❌ Don't share snapshot files containing personal data
313
+ ### `agent.replaceSnapshots(snapshotData)`
481
314
 
482
- ```gitignore
483
- # Exclude snapshots with real data
484
- /test/snapshots/production-*.json
485
- /test/snapshots/*-real-data.json
486
-
487
- # Include sanitized test snapshots
488
- !/test/snapshots/mock-*.json
489
- ```
315
+ <!-- YAML
316
+ added: v7.13.0
317
+ -->
490
318
 
491
- ## Error Handling
319
+ * `snapshotData` {Array} The snapshot data to load, replacing any existing
320
+ snapshots.
321
+ * `hash` {string} The hash used to key the snapshot.
322
+ * `snapshot` {Object} The snapshot entry.
323
+ * Returns: {undefined}
492
324
 
493
- ### Missing Snapshots in Playback Mode
325
+ Replaces all in-memory snapshots with the provided data.
494
326
 
495
- ```javascript
496
- try {
497
- const response = await fetch('https://api.example.com/nonexistent')
498
- } catch (error) {
499
- if (error.message.includes('No snapshot found')) {
500
- // Handle missing snapshot
501
- console.log('Snapshot not found for this request')
502
- }
503
- }
504
- ```
505
-
506
- ### Handling Network Errors in Record Mode
507
-
508
- ```javascript
509
- const agent = new SnapshotAgent({ mode: 'record', snapshotPath: './snapshots.json' })
510
-
511
- try {
512
- const response = await fetch('https://nonexistent-api.example.com/data')
513
- } catch (error) {
514
- // Network errors are not recorded as snapshots
515
- console.log('Network error:', error.message)
516
- }
517
- ```
518
-
519
- ## Best Practices
520
-
521
- ### 1. Organize Snapshots by Test Suite
522
-
523
- ```javascript
524
- // Use descriptive snapshot file names
525
- const agent = new SnapshotAgent({
526
- mode: 'playback',
527
- snapshotPath: `./test/snapshots/${testSuiteName}-${testName}.json`
528
- })
529
- ```
530
-
531
- ### 2. Version Control Snapshots
532
-
533
- Add snapshot files to version control to ensure consistent test behavior across environments:
534
-
535
- ```gitignore
536
- # Include snapshots in version control
537
- !/test/snapshots/*.json
538
- ```
539
-
540
- ### 3. Clean Up Test Data
541
-
542
- ```javascript
543
- test('API test', async (t) => {
544
- const agent = new SnapshotAgent({
545
- mode: 'playback',
546
- snapshotPath: './test/snapshots/temp-test.json'
547
- })
548
-
549
- // Clean up after test
550
- t.after(() => {
551
- agent.clearSnapshots()
552
- })
553
- })
554
- ```
555
-
556
- ### 4. Snapshot Validation
327
+ ```mjs
328
+ const recorder = agent.getRecorder()
329
+ const snapshots = recorder.getSnapshots()
557
330
 
558
- ```javascript
559
- test('validate snapshot contents', async (t) => {
560
- const agent = new SnapshotAgent({
561
- mode: 'playback',
562
- snapshotPath: './test/snapshots/validation.json'
563
- })
564
-
565
- const recorder = agent.getRecorder()
566
- const snapshots = recorder.getSnapshots()
567
-
568
- // Validate snapshot structure
569
- assert(snapshots.length > 0, 'Should have recorded snapshots')
570
- assert(snapshots[0].request.url.startsWith('https://'), 'Should use HTTPS')
571
- })
331
+ agent.replaceSnapshots(snapshots.map((snapshot, index) => ({
332
+ hash: `snapshot-${index}`,
333
+ snapshot
334
+ })))
572
335
  ```
573
336
 
574
- ## Comparison with Other Tools
337
+ ### `agent.close()`
575
338
 
576
- ### vs Manual MockAgent Setup
339
+ <!-- YAML
340
+ added: v7.13.0
341
+ -->
577
342
 
578
- **Manual MockAgent:**
579
- ```javascript
580
- const mockAgent = new MockAgent()
581
- const mockPool = mockAgent.get('https://api.example.com')
582
-
583
- mockPool.intercept({
584
- path: '/users',
585
- method: 'GET'
586
- }).reply(200, [
587
- { id: 1, name: 'User 1' },
588
- { id: 2, name: 'User 2' }
589
- ])
590
- ```
343
+ * Returns: {Promise<void>} Resolves once the agent and its resources are closed.
591
344
 
592
- **SnapshotAgent:**
593
- ```javascript
594
- // Record once
595
- const agent = new SnapshotAgent({ mode: 'record', snapshotPath: './snapshots.json' })
596
- // Real API call gets recorded automatically
345
+ Closes the agent and releases its resources. In `'record'` and `'update'` modes
346
+ the recorder is flushed to disk first. In `'playback'` mode nothing is written,
347
+ because matching a snapshot mutates its call count and saving would needlessly
348
+ rewrite the snapshot file. The real [`Agent`][], when one was created, and the
349
+ underlying [`MockAgent`][] are closed as well.
597
350
 
598
- // Use in tests
599
- const agent = new SnapshotAgent({ mode: 'playback', snapshotPath: './snapshots.json' })
600
- // Automatically replays recorded response
351
+ ```mjs
352
+ await agent.close()
601
353
  ```
602
354
 
603
- ### vs nock
604
-
605
- SnapshotAgent provides similar functionality to nock but is specifically designed for undici:
606
-
607
- - ✅ Works with all undici APIs (`request`, `stream`, `pipeline`, etc.)
608
- - ✅ Supports undici-specific features (RetryAgent, connection pooling)
609
- - ✅ Better TypeScript integration
610
- - ✅ More efficient for high-performance scenarios
611
-
612
- ## See Also
613
-
614
- - [MockAgent](./MockAgent.md) - Manual mocking for more control
615
- - [MockCallHistory](./MockCallHistory.md) - Inspecting request history
616
- - [Testing Best Practices](../best-practices/writing-tests.md) - General testing guidance
355
+ [`Agent`]: Agent.md#class-agent
356
+ [`Dispatcher`]: Dispatcher.md#class-dispatcher
357
+ [`InvalidArgumentError`]: Errors.md#undicierrorsundiciinvalidargumenterror
358
+ [`MockAgent`]: MockAgent.md#class-mockagent
359
+ [`UndiciError`]: Errors.md#undicierrorsundicierror
360
+ [`agent.getRecorder()`]: #agentgetrecorder
361
+ [`setGlobalDispatcher()`]: Dispatcher.md#setglobaldispatcherdispatcher