@mswjs/interceptors 0.41.8 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. package/README.md +274 -228
  2. package/lib/browser/{bufferUtils-BiiO6HZv.mjs → buffer-utils-DJj7YzLG.js} +3 -3
  3. package/lib/browser/buffer-utils-DJj7YzLG.js.map +1 -0
  4. package/lib/browser/create-request-id-DlEd4GOA.js +184 -0
  5. package/lib/browser/create-request-id-DlEd4GOA.js.map +1 -0
  6. package/lib/browser/{getRawRequest-B1BqgWG6.mjs → fetch-utils-zxA_SD66.js} +123 -52
  7. package/lib/browser/fetch-utils-zxA_SD66.js.map +1 -0
  8. package/lib/browser/handle-request-CIOa9O-N.js +167 -0
  9. package/lib/browser/handle-request-CIOa9O-N.js.map +1 -0
  10. package/lib/{node/hasConfigurableGlobal-BiTmog1u.mjs → browser/has-configurable-global-Cew-dYqk.js} +5 -7
  11. package/lib/browser/has-configurable-global-Cew-dYqk.js.map +1 -0
  12. package/lib/browser/http-CB9rQ7i_.d.ts +105 -0
  13. package/lib/browser/{index.d.cts → index.d.ts} +33 -38
  14. package/lib/browser/index.js +130 -0
  15. package/lib/browser/index.js.map +1 -0
  16. package/lib/browser/interceptor-dtJZ_9QT.d.ts +50 -0
  17. package/lib/browser/interceptors/WebSocket/index.d.ts +2 -0
  18. package/lib/browser/interceptors/WebSocket/{index.mjs → index.js} +40 -31
  19. package/lib/browser/interceptors/WebSocket/index.js.map +1 -0
  20. package/lib/browser/interceptors/XMLHttpRequest/web.d.ts +11 -0
  21. package/lib/browser/interceptors/XMLHttpRequest/web.js +2 -0
  22. package/lib/browser/interceptors/fetch/web.d.ts +14 -0
  23. package/lib/browser/interceptors/fetch/web.js +2 -0
  24. package/lib/browser/presets/browser.d.ts +11 -0
  25. package/lib/browser/presets/browser.js +12 -0
  26. package/lib/browser/presets/browser.js.map +1 -0
  27. package/lib/browser/{resolveWebSocketUrl-C83-x9iE.mjs → resolve-web-socket-url-CSvNPLGi.js} +3 -3
  28. package/lib/browser/resolve-web-socket-url-CSvNPLGi.js.map +1 -0
  29. package/lib/browser/web-BjVDkiX0.js +248 -0
  30. package/lib/browser/web-BjVDkiX0.js.map +1 -0
  31. package/lib/{node/XMLHttpRequest-DhupxLHX.mjs → browser/web-C2oKsT3Q.js} +328 -256
  32. package/lib/browser/web-C2oKsT3Q.js.map +1 -0
  33. package/lib/browser/{interceptors/WebSocket/index.d.cts → websocket-CC0nB0md.d.ts} +41 -33
  34. package/lib/node/batch-interceptor-ByEZVih3.js +119 -0
  35. package/lib/node/batch-interceptor-ByEZVih3.js.map +1 -0
  36. package/lib/node/batch-interceptor-CPjFK2td.d.ts +28 -0
  37. package/lib/node/buffer-utils-BvPY1Tc-.js +187 -0
  38. package/lib/node/buffer-utils-BvPY1Tc-.js.map +1 -0
  39. package/lib/node/fetch-utils-Dw1PsmtX.js +568 -0
  40. package/lib/node/fetch-utils-Dw1PsmtX.js.map +1 -0
  41. package/lib/node/has-configurable-global-CJCh_g1I.js +22 -0
  42. package/lib/node/has-configurable-global-CJCh_g1I.js.map +1 -0
  43. package/lib/node/http-CB9rQ7i_.d.ts +105 -0
  44. package/lib/{browser/interceptors/WebSocket/index.d.mts → node/index.d.ts} +120 -60
  45. package/lib/node/{index.mjs → index.js} +8 -11
  46. package/lib/node/index.js.map +1 -0
  47. package/lib/node/interceptor-dtJZ_9QT.d.ts +50 -0
  48. package/lib/node/interceptors/ClientRequest/index.d.ts +14 -0
  49. package/lib/node/interceptors/ClientRequest/index.js +67 -0
  50. package/lib/node/interceptors/ClientRequest/index.js.map +1 -0
  51. package/lib/node/interceptors/XMLHttpRequest/node.d.ts +12 -0
  52. package/lib/node/interceptors/XMLHttpRequest/node.js +74 -0
  53. package/lib/node/interceptors/XMLHttpRequest/node.js.map +1 -0
  54. package/lib/node/interceptors/fetch/node.d.ts +18 -0
  55. package/lib/node/interceptors/fetch/node.js +83 -0
  56. package/lib/node/interceptors/fetch/node.js.map +1 -0
  57. package/lib/node/interceptors/http/index.d.ts +14 -0
  58. package/lib/node/interceptors/http/index.js +32 -0
  59. package/lib/node/interceptors/http/index.js.map +1 -0
  60. package/lib/node/interceptors/net/index.d.ts +203 -0
  61. package/lib/node/interceptors/net/index.js +2 -0
  62. package/lib/node/llhttp/constants.cjs +485 -0
  63. package/lib/node/llhttp/constants.d.cts +957 -0
  64. package/lib/node/llhttp/llhttp.wasm +0 -0
  65. package/lib/node/net-DtMnyEeg.js +1388 -0
  66. package/lib/node/net-DtMnyEeg.js.map +1 -0
  67. package/lib/node/presets/node.d.ts +12 -0
  68. package/lib/node/presets/node.js +17 -0
  69. package/lib/node/presets/node.js.map +1 -0
  70. package/lib/node/{RemoteHttpInterceptor.d.cts → remote-http-interceptor.d.ts} +12 -11
  71. package/lib/node/{RemoteHttpInterceptor.mjs → remote-http-interceptor.js} +38 -33
  72. package/lib/node/remote-http-interceptor.js.map +1 -0
  73. package/lib/node/source-lP0yyEtA.js +1990 -0
  74. package/lib/node/source-lP0yyEtA.js.map +1 -0
  75. package/package.json +79 -118
  76. package/src/batch-interceptor.test.ts +475 -0
  77. package/src/batch-interceptor.ts +244 -0
  78. package/src/{createRequestId.test.ts → create-request-id.test.ts} +1 -2
  79. package/src/disposable.ts +13 -0
  80. package/src/events/http.ts +92 -0
  81. package/src/events/websocket.ts +47 -0
  82. package/src/glossary.ts +1 -27
  83. package/src/index.ts +18 -10
  84. package/src/interceptor.test.ts +279 -0
  85. package/src/interceptor.ts +139 -0
  86. package/src/interceptors/ClientRequest/index.test.ts +21 -39
  87. package/src/interceptors/ClientRequest/index.ts +65 -180
  88. package/src/interceptors/ClientRequest/utils/{recordRawHeaders.test.ts → record-raw-headers.test.ts} +1 -2
  89. package/src/interceptors/ClientRequest/utils/{recordRawHeaders.ts → record-raw-headers.ts} +29 -2
  90. package/src/interceptors/WebSocket/index.ts +34 -51
  91. package/src/interceptors/WebSocket/utils/{bindEvent.test.ts → bind-event.test.ts} +1 -2
  92. package/src/interceptors/WebSocket/utils/events.test.ts +0 -1
  93. package/src/interceptors/WebSocket/{WebSocketClassTransport.ts → web-socket-class-transport.ts} +3 -3
  94. package/src/interceptors/WebSocket/{WebSocketClientConnection.ts → web-socket-client-connection.ts} +4 -4
  95. package/src/interceptors/WebSocket/{WebSocketOverride.ts → web-socket-override.ts} +6 -7
  96. package/src/interceptors/WebSocket/{WebSocketServerConnection.ts → web-socket-server-connection.ts} +4 -4
  97. package/src/interceptors/WebSocket/{WebSocketTransport.ts → web-socket-transport.ts} +1 -1
  98. package/src/interceptors/XMLHttpRequest/node.ts +104 -0
  99. package/src/interceptors/XMLHttpRequest/polyfills/{ProgressEventPolyfill.ts → progress-event-polyfill.ts} +1 -1
  100. package/src/interceptors/XMLHttpRequest/utils/{concateArrayBuffer.test.ts → concat-array-buffer.test.ts} +1 -2
  101. package/src/interceptors/XMLHttpRequest/utils/{concatArrayBuffer.ts → concat-array-buffer.ts} +1 -1
  102. package/src/interceptors/XMLHttpRequest/utils/{createEvent.test.ts → create-event.test.ts} +3 -4
  103. package/src/interceptors/XMLHttpRequest/utils/{createEvent.ts → create-event.ts} +2 -2
  104. package/src/interceptors/XMLHttpRequest/utils/{createResponse.ts → create-response.ts} +1 -1
  105. package/src/interceptors/XMLHttpRequest/utils/{getBodyByteLength.test.ts → get-body-byte-length.test.ts} +1 -2
  106. package/src/interceptors/XMLHttpRequest/web.ts +34 -0
  107. package/src/interceptors/XMLHttpRequest/{XMLHttpRequestController.ts → xml-http-request-controller.ts} +363 -204
  108. package/src/interceptors/XMLHttpRequest/{XMLHttpRequestProxy.ts → xml-http-request-proxy.ts} +28 -25
  109. package/src/interceptors/fetch/node.ts +103 -0
  110. package/src/interceptors/fetch/utils/{followRedirect.ts → follow-redirect.ts} +1 -1
  111. package/src/interceptors/fetch/web.ts +217 -0
  112. package/src/interceptors/http/forward-events.test.ts +86 -0
  113. package/src/interceptors/http/forward-events.ts +139 -0
  114. package/src/interceptors/http/http-parser/index.ts +310 -0
  115. package/src/interceptors/http/http-parser/llhttp/constants.cjs +485 -0
  116. package/src/interceptors/http/http-parser/llhttp/constants.d.cts +957 -0
  117. package/src/interceptors/http/http-parser/llhttp/llhttp.wasm +0 -0
  118. package/src/interceptors/http/http-parser.ts +138 -0
  119. package/src/interceptors/http/index.ts +34 -0
  120. package/src/interceptors/http/source.ts +688 -0
  121. package/src/interceptors/net/index.ts +368 -0
  122. package/src/interceptors/net/socket-controller.ts +1476 -0
  123. package/src/interceptors/net/utils/address-info.ts +54 -0
  124. package/src/interceptors/net/utils/connection-options-to-url.ts +56 -0
  125. package/src/interceptors/net/utils/flush-writes.ts +57 -0
  126. package/src/interceptors/net/utils/get-tls-connect-options.ts +23 -0
  127. package/src/interceptors/net/utils/normalize-net-connect-args.test.ts +233 -0
  128. package/src/interceptors/net/utils/normalize-net-connect-args.ts +121 -0
  129. package/src/interceptors/net/utils/normalize-tls-connect-args.ts +50 -0
  130. package/src/presets/browser.ts +4 -4
  131. package/src/presets/node.ts +4 -4
  132. package/src/{RemoteHttpInterceptor.ts → remote-http-interceptor.ts} +55 -42
  133. package/src/request-context.ts +40 -0
  134. package/src/{RequestController.test.ts → request-controller.test.ts} +37 -3
  135. package/src/{RequestController.ts → request-controller.ts} +33 -11
  136. package/src/utils/{bufferUtils.test.ts → buffer-utils.test.ts} +1 -2
  137. package/src/utils/buffer-utils.ts +37 -0
  138. package/src/utils/{cloneObject.test.ts → clone-object.test.ts} +1 -2
  139. package/src/utils/{cloneObject.ts → clone-object.ts} +8 -8
  140. package/src/utils/{createProxy.test.ts → create-proxy.test.ts} +6 -4
  141. package/src/utils/{createProxy.ts → create-proxy.ts} +1 -1
  142. package/src/utils/{fetchUtils.test.ts → fetch-utils.test.ts} +1 -1
  143. package/src/utils/{fetchUtils.ts → fetch-utils.ts} +28 -3
  144. package/src/utils/{findPropertySource.test.ts → find-property-source.test.ts} +1 -2
  145. package/src/utils/{getCleanUrl.test.ts → get-clean-url.test.ts} +1 -2
  146. package/src/utils/{getUrlByRequestOptions.test.ts → get-url-by-request-options.test.ts} +4 -8
  147. package/src/utils/{getUrlByRequestOptions.ts → get-url-by-request-options.ts} +16 -16
  148. package/src/utils/{getValueBySymbol.test.ts → get-value-by-symbol.test.ts} +1 -2
  149. package/src/utils/{handleRequest.ts → handle-request.ts} +66 -47
  150. package/src/utils/{hasConfigurableGlobal.test.ts → has-configurable-global.test.ts} +1 -2
  151. package/src/utils/{hasConfigurableGlobal.ts → has-configurable-global.ts} +2 -4
  152. package/src/utils/{isObject.test.ts → is-object.test.ts} +1 -2
  153. package/src/utils/logger.test.ts +154 -0
  154. package/src/utils/logger.ts +154 -0
  155. package/src/utils/{parseJson.test.ts → parse-json.test.ts} +1 -2
  156. package/src/utils/{patchesRegistry.test.ts → patches-registry.test.ts} +1 -1
  157. package/src/utils/{patchesRegistry.ts → patches-registry.ts} +1 -1
  158. package/src/utils/{responseUtils.ts → response-utils.ts} +25 -2
  159. package/ClientRequest/package.json +0 -11
  160. package/RemoteHttpInterceptor/package.json +0 -11
  161. package/WebSocket/package.json +0 -12
  162. package/XMLHttpRequest/package.json +0 -12
  163. package/fetch/package.json +0 -12
  164. package/lib/browser/Interceptor-Deczogc8.d.cts +0 -65
  165. package/lib/browser/Interceptor-gqKgs-aF.d.mts +0 -65
  166. package/lib/browser/XMLHttpRequest-B11I9TBx.cjs +0 -751
  167. package/lib/browser/XMLHttpRequest-B11I9TBx.cjs.map +0 -1
  168. package/lib/browser/XMLHttpRequest-DHEkSoRN.mjs +0 -746
  169. package/lib/browser/XMLHttpRequest-DHEkSoRN.mjs.map +0 -1
  170. package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +0 -1
  171. package/lib/browser/bufferUtils-Uc0eRItL.cjs +0 -38
  172. package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +0 -1
  173. package/lib/browser/createRequestId-DOf8Ktjs.cjs +0 -205
  174. package/lib/browser/createRequestId-DOf8Ktjs.cjs.map +0 -1
  175. package/lib/browser/createRequestId-DYCsFHOi.mjs +0 -170
  176. package/lib/browser/createRequestId-DYCsFHOi.mjs.map +0 -1
  177. package/lib/browser/fetch-BJwfdses.mjs +0 -236
  178. package/lib/browser/fetch-BJwfdses.mjs.map +0 -1
  179. package/lib/browser/fetch-M8iXkZ3L.cjs +0 -241
  180. package/lib/browser/fetch-M8iXkZ3L.cjs.map +0 -1
  181. package/lib/browser/getRawRequest-B1BqgWG6.mjs.map +0 -1
  182. package/lib/browser/getRawRequest-DdfaiPVH.cjs +0 -376
  183. package/lib/browser/getRawRequest-DdfaiPVH.cjs.map +0 -1
  184. package/lib/browser/glossary-1lhZx6Aw.d.cts +0 -69
  185. package/lib/browser/glossary-nkHWcwvY.d.mts +0 -69
  186. package/lib/browser/handleRequest-1Yqu_ho_.mjs +0 -178
  187. package/lib/browser/handleRequest-1Yqu_ho_.mjs.map +0 -1
  188. package/lib/browser/handleRequest-Cz4_wmQ9.cjs +0 -189
  189. package/lib/browser/handleRequest-Cz4_wmQ9.cjs.map +0 -1
  190. package/lib/browser/hasConfigurableGlobal-C8zq1MCg.mjs +0 -109
  191. package/lib/browser/hasConfigurableGlobal-C8zq1MCg.mjs.map +0 -1
  192. package/lib/browser/hasConfigurableGlobal-CS7adEvV.cjs +0 -126
  193. package/lib/browser/hasConfigurableGlobal-CS7adEvV.cjs.map +0 -1
  194. package/lib/browser/index.cjs +0 -70
  195. package/lib/browser/index.cjs.map +0 -1
  196. package/lib/browser/index.d.mts +0 -125
  197. package/lib/browser/index.mjs +0 -56
  198. package/lib/browser/index.mjs.map +0 -1
  199. package/lib/browser/interceptors/WebSocket/index.cjs +0 -618
  200. package/lib/browser/interceptors/WebSocket/index.cjs.map +0 -1
  201. package/lib/browser/interceptors/WebSocket/index.mjs.map +0 -1
  202. package/lib/browser/interceptors/XMLHttpRequest/index.cjs +0 -8
  203. package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +0 -15
  204. package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +0 -15
  205. package/lib/browser/interceptors/XMLHttpRequest/index.mjs +0 -8
  206. package/lib/browser/interceptors/fetch/index.cjs +0 -7
  207. package/lib/browser/interceptors/fetch/index.d.cts +0 -13
  208. package/lib/browser/interceptors/fetch/index.d.mts +0 -13
  209. package/lib/browser/interceptors/fetch/index.mjs +0 -7
  210. package/lib/browser/presets/browser.cjs +0 -18
  211. package/lib/browser/presets/browser.cjs.map +0 -1
  212. package/lib/browser/presets/browser.d.cts +0 -12
  213. package/lib/browser/presets/browser.d.mts +0 -14
  214. package/lib/browser/presets/browser.mjs +0 -18
  215. package/lib/browser/presets/browser.mjs.map +0 -1
  216. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs +0 -31
  217. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs.map +0 -1
  218. package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs.map +0 -1
  219. package/lib/node/BatchInterceptor-DdMNfSUY.mjs +0 -44
  220. package/lib/node/BatchInterceptor-DdMNfSUY.mjs.map +0 -1
  221. package/lib/node/BatchInterceptor-KKF8Q47I.d.cts +0 -26
  222. package/lib/node/BatchInterceptor-Z1lwK23r.cjs +0 -49
  223. package/lib/node/BatchInterceptor-Z1lwK23r.cjs.map +0 -1
  224. package/lib/node/BatchInterceptor-rSr-NH_H.d.mts +0 -26
  225. package/lib/node/ClientRequest-DFs7FPNi.cjs +0 -1058
  226. package/lib/node/ClientRequest-DFs7FPNi.cjs.map +0 -1
  227. package/lib/node/ClientRequest-dRpI9v1o.mjs +0 -1049
  228. package/lib/node/ClientRequest-dRpI9v1o.mjs.map +0 -1
  229. package/lib/node/Interceptor-BsZ21ue0.d.cts +0 -132
  230. package/lib/node/Interceptor-soD-WpQO.d.mts +0 -132
  231. package/lib/node/RemoteHttpInterceptor.cjs +0 -155
  232. package/lib/node/RemoteHttpInterceptor.cjs.map +0 -1
  233. package/lib/node/RemoteHttpInterceptor.d.mts +0 -39
  234. package/lib/node/RemoteHttpInterceptor.mjs.map +0 -1
  235. package/lib/node/XMLHttpRequest-DhupxLHX.mjs.map +0 -1
  236. package/lib/node/XMLHttpRequest-Dyi6ahGz.cjs +0 -752
  237. package/lib/node/XMLHttpRequest-Dyi6ahGz.cjs.map +0 -1
  238. package/lib/node/bufferUtils-DxPxwff_.mjs +0 -20
  239. package/lib/node/bufferUtils-DxPxwff_.mjs.map +0 -1
  240. package/lib/node/bufferUtils-S5_-2eN4.cjs +0 -38
  241. package/lib/node/bufferUtils-S5_-2eN4.cjs.map +0 -1
  242. package/lib/node/chunk-CbDLau6x.cjs +0 -34
  243. package/lib/node/fetch-BqMcbuYR.mjs +0 -252
  244. package/lib/node/fetch-BqMcbuYR.mjs.map +0 -1
  245. package/lib/node/fetch-aQJu1Gf_.cjs +0 -259
  246. package/lib/node/fetch-aQJu1Gf_.cjs.map +0 -1
  247. package/lib/node/fetchUtils-BKJ1XmiO.mjs +0 -480
  248. package/lib/node/fetchUtils-BKJ1XmiO.mjs.map +0 -1
  249. package/lib/node/fetchUtils-umV5xXBy.cjs +0 -546
  250. package/lib/node/fetchUtils-umV5xXBy.cjs.map +0 -1
  251. package/lib/node/getRawRequest-B6znU6il.cjs +0 -36
  252. package/lib/node/getRawRequest-B6znU6il.cjs.map +0 -1
  253. package/lib/node/getRawRequest-C2-1urzA.mjs +0 -24
  254. package/lib/node/getRawRequest-C2-1urzA.mjs.map +0 -1
  255. package/lib/node/handleRequest-DCLzePtS.mjs +0 -190
  256. package/lib/node/handleRequest-DCLzePtS.mjs.map +0 -1
  257. package/lib/node/handleRequest-DVOthWJo.cjs +0 -220
  258. package/lib/node/handleRequest-DVOthWJo.cjs.map +0 -1
  259. package/lib/node/hasConfigurableGlobal-BiTmog1u.mjs.map +0 -1
  260. package/lib/node/hasConfigurableGlobal-MjY06_Ok.cjs +0 -108
  261. package/lib/node/hasConfigurableGlobal-MjY06_Ok.cjs.map +0 -1
  262. package/lib/node/index-BJ5E5aW-.d.cts +0 -113
  263. package/lib/node/index-DfoF45ih.d.mts +0 -113
  264. package/lib/node/index.cjs +0 -53
  265. package/lib/node/index.cjs.map +0 -1
  266. package/lib/node/index.d.cts +0 -104
  267. package/lib/node/index.d.mts +0 -104
  268. package/lib/node/index.mjs.map +0 -1
  269. package/lib/node/interceptors/ClientRequest/index.cjs +0 -6
  270. package/lib/node/interceptors/ClientRequest/index.d.cts +0 -2
  271. package/lib/node/interceptors/ClientRequest/index.d.mts +0 -3
  272. package/lib/node/interceptors/ClientRequest/index.mjs +0 -6
  273. package/lib/node/interceptors/XMLHttpRequest/index.cjs +0 -7
  274. package/lib/node/interceptors/XMLHttpRequest/index.d.cts +0 -14
  275. package/lib/node/interceptors/XMLHttpRequest/index.d.mts +0 -14
  276. package/lib/node/interceptors/XMLHttpRequest/index.mjs +0 -7
  277. package/lib/node/interceptors/fetch/index.cjs +0 -6
  278. package/lib/node/interceptors/fetch/index.d.cts +0 -12
  279. package/lib/node/interceptors/fetch/index.d.mts +0 -12
  280. package/lib/node/interceptors/fetch/index.mjs +0 -6
  281. package/lib/node/node-DIKcnzhK.cjs +0 -39
  282. package/lib/node/node-DIKcnzhK.cjs.map +0 -1
  283. package/lib/node/node-lsdNwZEW.mjs +0 -27
  284. package/lib/node/node-lsdNwZEW.mjs.map +0 -1
  285. package/lib/node/presets/node.cjs +0 -23
  286. package/lib/node/presets/node.cjs.map +0 -1
  287. package/lib/node/presets/node.d.cts +0 -13
  288. package/lib/node/presets/node.d.mts +0 -15
  289. package/lib/node/presets/node.mjs +0 -23
  290. package/lib/node/presets/node.mjs.map +0 -1
  291. package/lib/node/utils/node/index.cjs +0 -4
  292. package/lib/node/utils/node/index.d.cts +0 -16
  293. package/lib/node/utils/node/index.d.mts +0 -16
  294. package/lib/node/utils/node/index.mjs +0 -3
  295. package/presets/browser/package.json +0 -5
  296. package/presets/node/package.json +0 -11
  297. package/src/BatchInterceptor.test.ts +0 -255
  298. package/src/BatchInterceptor.ts +0 -95
  299. package/src/Interceptor.test.ts +0 -205
  300. package/src/Interceptor.ts +0 -249
  301. package/src/getRawRequest.ts +0 -21
  302. package/src/interceptors/ClientRequest/MockHttpSocket.ts +0 -724
  303. package/src/interceptors/ClientRequest/agents.ts +0 -110
  304. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +0 -54
  305. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +0 -45
  306. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +0 -427
  307. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +0 -268
  308. package/src/interceptors/ClientRequest/utils/parserUtils.ts +0 -48
  309. package/src/interceptors/Socket/MockSocket.test.ts +0 -264
  310. package/src/interceptors/Socket/MockSocket.ts +0 -58
  311. package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +0 -26
  312. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +0 -52
  313. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +0 -33
  314. package/src/interceptors/XMLHttpRequest/index.ts +0 -40
  315. package/src/interceptors/fetch/index.ts +0 -203
  316. package/src/utils/bufferUtils.ts +0 -22
  317. package/src/utils/canParseUrl.ts +0 -13
  318. package/src/utils/emitAsync.ts +0 -25
  319. package/src/utils/nextTick.ts +0 -11
  320. package/src/utils/node/index.ts +0 -39
  321. /package/src/{createRequestId.ts → create-request-id.ts} +0 -0
  322. /package/src/{InterceptorError.ts → interceptor-error.ts} +0 -0
  323. /package/src/interceptors/WebSocket/utils/{bindEvent.ts → bind-event.ts} +0 -0
  324. /package/src/interceptors/XMLHttpRequest/polyfills/{EventPolyfill.ts → event-polyfill.ts} +0 -0
  325. /package/src/interceptors/XMLHttpRequest/utils/{getBodyByteLength.ts → get-body-byte-length.ts} +0 -0
  326. /package/src/interceptors/XMLHttpRequest/utils/{isDomParserSupportedType.ts → is-dom-parser-supported-type.ts} +0 -0
  327. /package/src/interceptors/fetch/utils/{createNetworkError.ts → create-network-error.ts} +0 -0
  328. /package/src/utils/{findPropertySource.ts → find-property-source.ts} +0 -0
  329. /package/src/utils/{getCleanUrl.ts → get-clean-url.ts} +0 -0
  330. /package/src/utils/{getValueBySymbol.ts → get-value-by-symbol.ts} +0 -0
  331. /package/src/utils/{isNodeLikeError.ts → is-node-like-error.ts} +0 -0
  332. /package/src/utils/{isObject.ts → is-object.ts} +0 -0
  333. /package/src/utils/{isPropertyAccessible.ts → is-property-accessible.ts} +0 -0
  334. /package/src/utils/{parseJson.ts → parse-json.ts} +0 -0
  335. /package/src/utils/{resolveWebSocketUrl.ts → resolve-web-socket-url.ts} +0 -0
@@ -1,12 +1,12 @@
1
- import type { Logger } from '@open-draft/logger'
2
- import { XMLHttpRequestEmitter } from '.'
3
- import { RequestController } from '../../RequestController'
4
- import { XMLHttpRequestController } from './XMLHttpRequestController'
5
- import { handleRequest } from '../../utils/handleRequest'
6
- import { isResponseError } from '../../utils/responseUtils'
1
+ import type { Emitter } from 'rettime'
2
+ import { HttpResponseEvent, type HttpRequestEventMap } from '../../events/http'
3
+ import { RequestController } from '../../request-controller'
4
+ import { XMLHttpRequestController } from './xml-http-request-controller'
5
+ import { handleRequest } from '../../utils/handle-request'
6
+ import type { Logger } from '../../utils/logger'
7
7
 
8
8
  export interface XMLHttpRequestProxyOptions {
9
- emitter: XMLHttpRequestEmitter
9
+ emitter: Emitter<HttpRequestEventMap>
10
10
  logger: Logger
11
11
  }
12
12
 
@@ -21,7 +21,7 @@ export function createXMLHttpRequestProxy({
21
21
  }: XMLHttpRequestProxyOptions) {
22
22
  const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {
23
23
  construct(target, args, newTarget) {
24
- logger.info('constructed new XMLHttpRequest')
24
+ logger.verbose('constructed new XMLHttpRequest')
25
25
 
26
26
  const originalRequest = Reflect.construct(
27
27
  target,
@@ -55,59 +55,62 @@ export function createXMLHttpRequestProxy({
55
55
  xhrRequestController.onRequest = async function ({ request, requestId }) {
56
56
  const controller = new RequestController(request, {
57
57
  passthrough: () => {
58
- this.logger.info(
58
+ this.logger.verbose(
59
59
  'no mocked response received, performing request as-is...'
60
60
  )
61
61
  },
62
62
  respondWith: async (response) => {
63
- if (isResponseError(response)) {
64
- this.errorWith(new TypeError('Network error'))
65
- return
66
- }
67
-
68
63
  await this.respondWith(response)
69
64
  },
70
65
  errorWith: (reason) => {
71
- this.logger.info('request errored!', { error: reason })
66
+ this.logger.verbose('request errored %o', { error: reason })
72
67
 
73
68
  if (reason instanceof Error) {
74
69
  this.errorWith(reason)
75
70
  }
76
71
  },
72
+ }, {
73
+ logger,
74
+ requestId,
77
75
  })
78
76
 
79
- this.logger.info('awaiting mocked response...')
77
+ this.logger.verbose('awaiting mocked response')
80
78
 
81
- this.logger.info(
79
+ this.logger.verbose(
82
80
  'emitting the "request" event for %s listener(s)...',
83
81
  emitter.listenerCount('request')
84
82
  )
85
83
 
86
84
  await handleRequest({
85
+ initiator: this.request,
87
86
  request,
88
87
  requestId,
89
88
  controller,
90
89
  emitter,
90
+ logger,
91
91
  })
92
92
  }
93
93
 
94
94
  xhrRequestController.onResponse = async function ({
95
95
  response,
96
- isMockedResponse,
96
+ responseType,
97
97
  request,
98
98
  requestId,
99
99
  }) {
100
- this.logger.info(
100
+ this.logger.verbose(
101
101
  'emitting the "response" event for %s listener(s)...',
102
102
  emitter.listenerCount('response')
103
103
  )
104
104
 
105
- emitter.emit('response', {
106
- response,
107
- isMockedResponse,
108
- request,
109
- requestId,
110
- })
105
+ await emitter.emitAsPromise(
106
+ new HttpResponseEvent({
107
+ initiator: this.request,
108
+ response,
109
+ responseType,
110
+ request,
111
+ requestId,
112
+ })
113
+ )
111
114
  }
112
115
 
113
116
  // Return the proxied request from the controller
@@ -0,0 +1,103 @@
1
+ import { hasConfigurableGlobal } from '#/src/utils/has-configurable-global'
2
+ import { getErrorResponse } from '#/src/utils/response-utils'
3
+ import { requestContext } from '#/src/request-context'
4
+ import { patchesRegistry } from '#/src/utils/patches-registry'
5
+ import { forwardHttpEvents } from '#/src/interceptors/http/forward-events'
6
+ import { NodeHttpRequestSource } from '#/src/interceptors/http/source'
7
+ import { HttpRequestEventMap } from '#/src/events/http'
8
+ import { Interceptor } from '../../interceptor'
9
+
10
+ /**
11
+ * Interceptor for `fetch` requests in Node.js.
12
+ * @note This interceptor only affects requests performed via
13
+ * the global `fetch` function. To intercept fetch requests performed
14
+ * by other means (e.g. direct `request()` from Undici) use the
15
+ * `HttpRequestInterceptor` instead.
16
+ */
17
+ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
18
+ static symbol = Symbol.for('fetch-interceptor')
19
+
20
+ protected predicate() {
21
+ return hasConfigurableGlobal('fetch')
22
+ }
23
+
24
+ protected setup(): void {
25
+ const requestSource = Interceptor.singleton(NodeHttpRequestSource)
26
+ requestSource.apply(this)
27
+
28
+ this.subscriptions.push(() => {
29
+ requestSource.dispose(this)
30
+ })
31
+
32
+ this.subscriptions.push(
33
+ forwardHttpEvents({
34
+ source: requestSource,
35
+ emitter: this.emitter,
36
+ predicate: (initiator) => {
37
+ return initiator instanceof Request
38
+ },
39
+ responsePredicate: (event) => {
40
+ /**
41
+ * @note Fetch clients never observe informational responses (1xx).
42
+ * Undici treats them as a network error, failing the request,
43
+ * so do not forward their "response" events to fetch consumers.
44
+ */
45
+ return event.response.status >= 200
46
+ },
47
+ })
48
+ )
49
+
50
+ this.subscriptions.push(
51
+ patchesRegistry.applyPatch(globalThis, 'fetch', (realFetch) => {
52
+ return (input, init) => {
53
+ /**
54
+ * Resolve potentially relative request URL against the present `location`.
55
+ * This is mainly for native `fetch` in browser-like environments.
56
+ * @see https://github.com/mswjs/msw/issues/1625
57
+ */
58
+ const resolvedInput =
59
+ typeof input === 'string' &&
60
+ typeof location !== 'undefined' &&
61
+ !URL.canParse(input)
62
+ ? new URL(input, location.href)
63
+ : input
64
+
65
+ const request = new Request(resolvedInput, init)
66
+
67
+ /**
68
+ * @note Scope the request context to the `fetch` call itself.
69
+ * Using `enterWith` here would rebind the store for the caller's
70
+ * entire asynchronous scope, attributing unrelated requests
71
+ * performed after this `fetch` to it.
72
+ */
73
+ return requestContext.run(
74
+ {
75
+ initiator: request,
76
+ logger: this.logger,
77
+ },
78
+ () => {
79
+ return realFetch(request).catch((error: unknown) => {
80
+ /**
81
+ * @note A mocked `Response.error()` destroys the socket with
82
+ * an internal error, which Undici reports as the cause of its
83
+ * "fetch failed" rejection. Surface the error response as the
84
+ * rejection cause instead, so the consumer can tell a mocked
85
+ * network error apart from an actual connectivity issue.
86
+ */
87
+ if (error instanceof TypeError) {
88
+ const errorResponse = getErrorResponse(error.cause)
89
+
90
+ if (errorResponse) {
91
+ error.cause = errorResponse
92
+ }
93
+ }
94
+
95
+ throw error
96
+ })
97
+ }
98
+ )
99
+ }
100
+ })
101
+ )
102
+ }
103
+ }
@@ -1,4 +1,4 @@
1
- import { createNetworkError } from './createNetworkError'
1
+ import { createNetworkError } from './create-network-error'
2
2
 
3
3
  const REQUEST_BODY_HEADERS = [
4
4
  'content-encoding',
@@ -0,0 +1,217 @@
1
+ import { until } from '@open-draft/until'
2
+ import { HttpResponseEvent, type HttpRequestEventMap } from '../../events/http'
3
+ import { RequestController } from '../../request-controller'
4
+ import { handleRequest } from '../../utils/handle-request'
5
+ import { createRequestId } from '../../create-request-id'
6
+ import { createNetworkError } from './utils/create-network-error'
7
+ import { followFetchRedirect } from './utils/follow-redirect'
8
+ import { decompressResponse } from './utils/decompression'
9
+ import { hasConfigurableGlobal } from '../../utils/has-configurable-global'
10
+ import { FetchResponse } from '../../utils/fetch-utils'
11
+ import { isResponseError } from '../../utils/response-utils'
12
+ import { patchesRegistry } from '../../utils/patches-registry'
13
+ import { copyRawHeaders } from '../ClientRequest/utils/record-raw-headers'
14
+ import { Interceptor } from '../../interceptor'
15
+ import { createLogger } from '../../utils/logger'
16
+
17
+ const logger = createLogger('fetch')
18
+
19
+ /**
20
+ * Interceptor for `fetch` requests in the browser.
21
+ */
22
+ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
23
+ static symbol = Symbol.for('fetch-interceptor')
24
+
25
+ protected predicate() {
26
+ return hasConfigurableGlobal('fetch')
27
+ }
28
+
29
+ protected async setup() {
30
+ logger.verbose('patching global fetch...')
31
+
32
+ this.subscriptions.push(
33
+ patchesRegistry.applyPatch(globalThis, 'fetch', (realFetch) => {
34
+ return async (input, init) => {
35
+ const requestId = createRequestId()
36
+
37
+ /**
38
+ * @note Resolve potentially relative request URL
39
+ * against the present `location`. This is mainly
40
+ * for native `fetch` in JSDOM.
41
+ * @see https://github.com/mswjs/msw/issues/1625
42
+ */
43
+ const resolvedInput =
44
+ typeof input === 'string' &&
45
+ typeof location !== 'undefined' &&
46
+ !URL.canParse(input)
47
+ ? new URL(input, location.href)
48
+ : input
49
+
50
+ const request = new Request(resolvedInput, init)
51
+
52
+ const responsePromise = Promise.withResolvers<Response>()
53
+
54
+ const controller = new RequestController(
55
+ request,
56
+ {
57
+ passthrough: async () => {
58
+ logger.verbose('performing request as-is')
59
+
60
+ /**
61
+ * @note Clone the request instance right before performing it.
62
+ * This preserves any modifications made to the intercepted request
63
+ * in the "request" listener. This also allows the user to read the
64
+ * request body in the "response" listener (otherwise "unusable").
65
+ */
66
+ const requestCloneForResponseEvent = request.clone()
67
+
68
+ // Perform the intercepted request as-is.
69
+ const [responseError, originalResponse] = await until(() =>
70
+ realFetch(request)
71
+ )
72
+
73
+ if (responseError) {
74
+ return responsePromise.reject(responseError)
75
+ }
76
+
77
+ logger.verbose('original fetch performed %o', originalResponse)
78
+
79
+ if (this.emitter.listenerCount('response') > 0) {
80
+ logger.verbose('emitting the "response" event')
81
+
82
+ const responseClone = FetchResponse.clone(originalResponse)
83
+ await this.emitter.emitAsPromise(
84
+ new HttpResponseEvent({
85
+ initiator: requestCloneForResponseEvent,
86
+ request: requestCloneForResponseEvent,
87
+ requestId,
88
+ response: responseClone,
89
+ responseType: 'original',
90
+ })
91
+ )
92
+ }
93
+
94
+ // Resolve the response promise with the original response
95
+ // since the `fetch()` return this internal promise.
96
+ responsePromise.resolve(originalResponse)
97
+ },
98
+ respondWith: async (rawResponse) => {
99
+ // Handle mocked `Response.error()` (i.e. request errors).
100
+ if (isResponseError(rawResponse)) {
101
+ logger.verbose('request errored %o', {
102
+ response: rawResponse,
103
+ })
104
+ responsePromise.reject(createNetworkError(rawResponse))
105
+ return
106
+ }
107
+
108
+ // Decompress the mocked response body, if applicable.
109
+ const decompressedStream = decompressResponse(rawResponse)
110
+ const response = new FetchResponse(
111
+ decompressedStream || rawResponse.body,
112
+ {
113
+ url: request.url,
114
+ status: rawResponse.status,
115
+ statusText: rawResponse.statusText,
116
+ headers: rawResponse.headers,
117
+ }
118
+ )
119
+
120
+ copyRawHeaders(rawResponse.headers, response.headers)
121
+
122
+ /**
123
+ * Undici's handling of following redirect responses.
124
+ * Treat the "manual" redirect mode as a regular mocked response.
125
+ * This way, the client can manually follow the redirect it receives.
126
+ * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173
127
+ */
128
+ if (FetchResponse.isRedirectResponse(response.status)) {
129
+ // Reject the request promise if its `redirect` is set to `error`
130
+ // and it receives a mocked redirect response.
131
+ if (request.redirect === 'error') {
132
+ responsePromise.reject(
133
+ createNetworkError('unexpected redirect')
134
+ )
135
+ return
136
+ }
137
+
138
+ if (request.redirect === 'follow') {
139
+ followFetchRedirect(request, response).then(
140
+ (response) => {
141
+ responsePromise.resolve(response)
142
+ },
143
+ (reason) => {
144
+ responsePromise.reject(reason)
145
+ }
146
+ )
147
+ return
148
+ }
149
+ }
150
+
151
+ if (this.emitter.listenerCount('response') > 0) {
152
+ logger.verbose('emitting the "response" event')
153
+
154
+ // Await the response listeners to finish before resolving
155
+ // the response promise. This ensures all your logic finishes
156
+ // before the interceptor resolves the pending response.
157
+ await this.emitter.emitAsPromise(
158
+ new HttpResponseEvent({
159
+ initiator: request,
160
+ // Clone the mocked response for the "response" event listener.
161
+ // This way, the listener can read the response and not lock its body
162
+ // for the actual fetch consumer.
163
+ response: FetchResponse.clone(response),
164
+ responseType: 'mock',
165
+ request,
166
+ requestId,
167
+ })
168
+ )
169
+ }
170
+
171
+ responsePromise.resolve(response)
172
+ },
173
+ errorWith: (reason) => {
174
+ logger.verbose('request aborted %o', { reason })
175
+ responsePromise.reject(reason)
176
+ },
177
+ },
178
+ {
179
+ logger,
180
+ requestId,
181
+ }
182
+ )
183
+
184
+ logger.verbose('awaiting request resolution')
185
+
186
+ logger.verbose(
187
+ 'emitting the "request" event for %s listener(s)...',
188
+ this.emitter.listenerCount('request')
189
+ )
190
+
191
+ /**
192
+ * @note Give the consumer a chance to abort the request before
193
+ * it is dispatched. Fetch queues the request processing as a
194
+ * task, so a signal aborted synchronously after `fetch()` must
195
+ * prevent the request from ever reaching the "request" listeners.
196
+ * Without this, the first listener is invoked synchronously
197
+ * within the `fetch()` call itself.
198
+ */
199
+ await Promise.resolve()
200
+
201
+ await handleRequest({
202
+ initiator: request,
203
+ request,
204
+ requestId,
205
+ emitter: this.emitter,
206
+ controller,
207
+ logger,
208
+ })
209
+
210
+ return responsePromise.promise
211
+ }
212
+ })
213
+ )
214
+
215
+ logger.verbose('global fetch patched: %s', globalThis.fetch.name)
216
+ }
217
+ }
@@ -0,0 +1,86 @@
1
+ import { Emitter } from 'rettime'
2
+ import {
3
+ HttpResponseEvent,
4
+ type HttpRequestEventMap,
5
+ } from '#/src/events/http'
6
+ import { Interceptor } from '#/src/interceptor'
7
+ import { forwardHttpEvents } from './forward-events'
8
+
9
+ class HttpRequestSource extends Interceptor<HttpRequestEventMap> {
10
+ protected predicate(): boolean {
11
+ return true
12
+ }
13
+
14
+ protected setup(): void {}
15
+
16
+ public emitResponse(event: HttpResponseEvent) {
17
+ return this.emitter.emitAsPromise(event)
18
+ }
19
+ }
20
+
21
+ it('forwards the canonical event instance to every interceptor', async () => {
22
+ const source = new HttpRequestSource()
23
+ const firstEmitter = new Emitter<HttpRequestEventMap>()
24
+ const secondEmitter = new Emitter<HttpRequestEventMap>()
25
+ const firstListener = vi.fn()
26
+ const secondListener = vi.fn()
27
+
28
+ firstEmitter.on('response', firstListener)
29
+ secondEmitter.on('response', secondListener)
30
+
31
+ const disposeFirstForwarding = forwardHttpEvents({
32
+ source,
33
+ emitter: firstEmitter,
34
+ predicate: () => {
35
+ return true
36
+ },
37
+ })
38
+ const disposeSecondForwarding = forwardHttpEvents({
39
+ source,
40
+ emitter: secondEmitter,
41
+ predicate: () => {
42
+ return true
43
+ },
44
+ })
45
+ const responseEvent = new HttpResponseEvent({
46
+ request: new Request('https://example.com'),
47
+ requestId: 'request-id',
48
+ initiator: null,
49
+ response: new Response(),
50
+ responseType: 'mock',
51
+ })
52
+
53
+ await source.emitResponse(responseEvent)
54
+
55
+ expect(firstListener).toHaveBeenCalledExactlyOnceWith(responseEvent)
56
+ expect(secondListener).toHaveBeenCalledExactlyOnceWith(responseEvent)
57
+
58
+ disposeFirstForwarding()
59
+ disposeSecondForwarding()
60
+ })
61
+
62
+ it('removes lazy source listeners with the consumer listener', () => {
63
+ const source = new HttpRequestSource()
64
+ const emitter = new Emitter<HttpRequestEventMap>()
65
+ const listener = vi.fn()
66
+
67
+ emitter.on('response', listener)
68
+ const disposeForwarding = forwardHttpEvents({
69
+ source,
70
+ emitter,
71
+ predicate: () => {
72
+ return true
73
+ },
74
+ })
75
+
76
+ expect(source.listenerCount('request')).toBe(1)
77
+ expect(source.listenerCount('response')).toBe(1)
78
+
79
+ emitter.removeListener('response', listener)
80
+
81
+ expect(source.listenerCount('response')).toBe(0)
82
+
83
+ disposeForwarding()
84
+
85
+ expect(source.listenerCount('request')).toBe(0)
86
+ })
@@ -0,0 +1,139 @@
1
+ import { type Emitter } from 'rettime'
2
+ import {
3
+ type HttpRequestEventMap,
4
+ type HttpResponseEvent,
5
+ } from '#/src/events/http'
6
+ import { type Interceptor } from '#/src/interceptor'
7
+ import { type DisposableSubscription } from '#/src/disposable'
8
+ import { createLogger } from '#/src/utils/logger'
9
+
10
+ const logger = createLogger('http-request')
11
+
12
+ interface ForwardHttpEventsOptions {
13
+ source: Interceptor<HttpRequestEventMap>
14
+ emitter: Emitter<HttpRequestEventMap>
15
+ predicate: (initiator: unknown) => boolean
16
+ responsePredicate?: (event: HttpResponseEvent) => boolean
17
+ }
18
+
19
+ export function forwardHttpEvents(
20
+ options: ForwardHttpEventsOptions
21
+ ): DisposableSubscription {
22
+ const controller = new AbortController()
23
+ const { source, emitter, predicate, responsePredicate } = options
24
+
25
+ source.on(
26
+ 'request',
27
+ async (event) => {
28
+ if (predicate(event.initiator)) {
29
+ logger.verbose('forwarding "request" event %o', {
30
+ requestId: event.requestId,
31
+ })
32
+ await emitter.emitAsPromise(event)
33
+ }
34
+ },
35
+ {
36
+ signal: controller.signal,
37
+ }
38
+ )
39
+
40
+ const responseListener: Emitter.Listener<
41
+ Emitter<HttpRequestEventMap>,
42
+ 'response'
43
+ > = async (event) => {
44
+ if (
45
+ predicate(event.initiator) &&
46
+ (responsePredicate == null || responsePredicate(event))
47
+ ) {
48
+ logger.verbose('forwarding "response" event %o', {
49
+ requestId: event.requestId,
50
+ responseType: event.responseType,
51
+ })
52
+ await emitter.emitAsPromise(event)
53
+ }
54
+ }
55
+
56
+ const unhandledExceptionListener: Emitter.Listener<
57
+ Emitter<HttpRequestEventMap>,
58
+ 'unhandledException'
59
+ > = async (event) => {
60
+ if (predicate(event.initiator)) {
61
+ logger.verbose('forwarding "unhandledException" event %o', {
62
+ requestId: event.requestId,
63
+ })
64
+ await emitter.emitAsPromise(event)
65
+ }
66
+ }
67
+
68
+ const addResponseListener = (): void => {
69
+ if (!source.listeners('response').includes(responseListener)) {
70
+ source.on('response', responseListener, {
71
+ signal: controller.signal,
72
+ })
73
+ }
74
+ }
75
+
76
+ const addUnhandledExceptionListener = (): void => {
77
+ if (
78
+ !source
79
+ .listeners('unhandledException')
80
+ .includes(unhandledExceptionListener)
81
+ ) {
82
+ source.on('unhandledException', unhandledExceptionListener, {
83
+ signal: controller.signal,
84
+ })
85
+ }
86
+ }
87
+
88
+ if (emitter.listenerCount('response') > 0) {
89
+ addResponseListener()
90
+ }
91
+
92
+ if (emitter.listenerCount('unhandledException') > 0) {
93
+ addUnhandledExceptionListener()
94
+ }
95
+
96
+ emitter.hooks.on(
97
+ 'newListener',
98
+ (type) => {
99
+ if (type === 'response') {
100
+ addResponseListener()
101
+ }
102
+
103
+ if (type === 'unhandledException') {
104
+ addUnhandledExceptionListener()
105
+ }
106
+ },
107
+ {
108
+ signal: controller.signal,
109
+ persist: true,
110
+ }
111
+ )
112
+
113
+ emitter.hooks.on(
114
+ 'removeListener',
115
+ (type) => {
116
+ if (type === 'response' && emitter.listenerCount('response') === 0) {
117
+ source.removeListener('response', responseListener)
118
+ }
119
+
120
+ if (
121
+ type === 'unhandledException' &&
122
+ emitter.listenerCount('unhandledException') === 0
123
+ ) {
124
+ source.removeListener(
125
+ 'unhandledException',
126
+ unhandledExceptionListener
127
+ )
128
+ }
129
+ },
130
+ {
131
+ signal: controller.signal,
132
+ persist: true,
133
+ }
134
+ )
135
+
136
+ return () => {
137
+ controller.abort()
138
+ }
139
+ }