msw 2.12.13 → 2.13.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 (272) hide show
  1. package/lib/browser/index.d.mts +29 -19
  2. package/lib/browser/index.d.ts +29 -19
  3. package/lib/browser/index.js +1763 -1321
  4. package/lib/browser/index.js.map +1 -1
  5. package/lib/browser/index.mjs +1769 -1321
  6. package/lib/browser/index.mjs.map +1 -1
  7. package/lib/core/{HttpResponse-Dj6ibgFJ.d.ts → HttpResponse-CksOMVAa.d.ts} +5 -5
  8. package/lib/core/{HttpResponse-Be4eT3x6.d.mts → HttpResponse-DlRR1D-f.d.mts} +5 -5
  9. package/lib/core/HttpResponse.d.mts +1 -1
  10. package/lib/core/HttpResponse.d.ts +1 -1
  11. package/lib/core/experimental/compat.d.mts +17 -0
  12. package/lib/core/experimental/compat.d.ts +17 -0
  13. package/lib/core/experimental/compat.js +54 -0
  14. package/lib/core/experimental/compat.js.map +1 -0
  15. package/lib/core/experimental/compat.mjs +36 -0
  16. package/lib/core/experimental/compat.mjs.map +1 -0
  17. package/lib/core/experimental/define-network.d.mts +75 -0
  18. package/lib/core/experimental/define-network.d.ts +75 -0
  19. package/lib/core/experimental/define-network.js +124 -0
  20. package/lib/core/experimental/define-network.js.map +1 -0
  21. package/lib/core/experimental/define-network.mjs +107 -0
  22. package/lib/core/experimental/define-network.mjs.map +1 -0
  23. package/lib/core/experimental/frames/http-frame.d.mts +77 -0
  24. package/lib/core/experimental/frames/http-frame.d.ts +77 -0
  25. package/lib/core/experimental/frames/http-frame.js +194 -0
  26. package/lib/core/experimental/frames/http-frame.js.map +1 -0
  27. package/lib/core/experimental/frames/http-frame.mjs +176 -0
  28. package/lib/core/experimental/frames/http-frame.mjs.map +1 -0
  29. package/lib/core/experimental/frames/network-frame.d.mts +12 -0
  30. package/lib/core/experimental/frames/network-frame.d.ts +12 -0
  31. package/lib/core/{handlers/common.js → experimental/frames/network-frame.js} +19 -3
  32. package/lib/core/experimental/frames/network-frame.js.map +1 -0
  33. package/lib/core/experimental/frames/network-frame.mjs +13 -0
  34. package/lib/core/experimental/frames/network-frame.mjs.map +1 -0
  35. package/lib/core/experimental/frames/websocket-frame.d.mts +55 -0
  36. package/lib/core/experimental/frames/websocket-frame.d.ts +55 -0
  37. package/lib/core/experimental/frames/websocket-frame.js +129 -0
  38. package/lib/core/experimental/frames/websocket-frame.js.map +1 -0
  39. package/lib/core/experimental/frames/websocket-frame.mjs +116 -0
  40. package/lib/core/experimental/frames/websocket-frame.mjs.map +1 -0
  41. package/lib/core/experimental/handlers-controller.d.mts +35 -0
  42. package/lib/core/experimental/handlers-controller.d.ts +35 -0
  43. package/lib/core/experimental/handlers-controller.js +121 -0
  44. package/lib/core/experimental/handlers-controller.js.map +1 -0
  45. package/lib/core/experimental/handlers-controller.mjs +101 -0
  46. package/lib/core/experimental/handlers-controller.mjs.map +1 -0
  47. package/lib/core/experimental/index.d.mts +17 -0
  48. package/lib/core/experimental/index.d.ts +17 -0
  49. package/lib/core/experimental/index.js +36 -0
  50. package/lib/core/experimental/index.js.map +1 -0
  51. package/lib/core/experimental/index.mjs +20 -0
  52. package/lib/core/experimental/index.mjs.map +1 -0
  53. package/lib/core/experimental/on-unhandled-frame.d.mts +12 -0
  54. package/lib/core/experimental/on-unhandled-frame.d.ts +12 -0
  55. package/lib/core/experimental/on-unhandled-frame.js +90 -0
  56. package/lib/core/experimental/on-unhandled-frame.js.map +1 -0
  57. package/lib/core/experimental/on-unhandled-frame.mjs +70 -0
  58. package/lib/core/experimental/on-unhandled-frame.mjs.map +1 -0
  59. package/lib/core/experimental/request-utils.d.mts +12 -0
  60. package/lib/core/experimental/request-utils.d.ts +12 -0
  61. package/lib/core/experimental/request-utils.js +50 -0
  62. package/lib/core/experimental/request-utils.js.map +1 -0
  63. package/lib/core/experimental/request-utils.mjs +30 -0
  64. package/lib/core/experimental/request-utils.mjs.map +1 -0
  65. package/lib/core/experimental/setup-api.d.mts +33 -0
  66. package/lib/core/experimental/setup-api.d.ts +33 -0
  67. package/lib/core/experimental/setup-api.js +61 -0
  68. package/lib/core/experimental/setup-api.js.map +1 -0
  69. package/lib/core/experimental/setup-api.mjs +43 -0
  70. package/lib/core/experimental/setup-api.mjs.map +1 -0
  71. package/lib/core/experimental/sources/interceptor-source.d.mts +28 -0
  72. package/lib/core/experimental/sources/interceptor-source.d.ts +28 -0
  73. package/lib/core/experimental/sources/interceptor-source.js +142 -0
  74. package/lib/core/experimental/sources/interceptor-source.js.map +1 -0
  75. package/lib/core/experimental/sources/interceptor-source.mjs +124 -0
  76. package/lib/core/experimental/sources/interceptor-source.mjs.map +1 -0
  77. package/lib/core/experimental/sources/network-source.d.mts +31 -0
  78. package/lib/core/experimental/sources/network-source.d.ts +31 -0
  79. package/lib/core/experimental/sources/network-source.js +50 -0
  80. package/lib/core/experimental/sources/network-source.js.map +1 -0
  81. package/lib/core/experimental/sources/network-source.mjs +30 -0
  82. package/lib/core/experimental/sources/network-source.mjs.map +1 -0
  83. package/lib/core/getResponse.d.mts +1 -1
  84. package/lib/core/getResponse.d.ts +1 -1
  85. package/lib/core/graphql.d.mts +1 -1
  86. package/lib/core/graphql.d.ts +1 -1
  87. package/lib/core/handlers/GraphQLHandler.d.mts +1 -1
  88. package/lib/core/handlers/GraphQLHandler.d.ts +1 -1
  89. package/lib/core/handlers/HttpHandler.d.mts +1 -1
  90. package/lib/core/handlers/HttpHandler.d.ts +1 -1
  91. package/lib/core/handlers/RequestHandler.d.mts +1 -1
  92. package/lib/core/handlers/RequestHandler.d.ts +1 -1
  93. package/lib/core/handlers/RequestHandler.js +5 -6
  94. package/lib/core/handlers/RequestHandler.js.map +1 -1
  95. package/lib/core/handlers/RequestHandler.mjs +5 -6
  96. package/lib/core/handlers/RequestHandler.mjs.map +1 -1
  97. package/lib/core/handlers/WebSocketHandler.d.mts +8 -4
  98. package/lib/core/handlers/WebSocketHandler.d.ts +8 -4
  99. package/lib/core/handlers/WebSocketHandler.js +18 -5
  100. package/lib/core/handlers/WebSocketHandler.js.map +1 -1
  101. package/lib/core/handlers/WebSocketHandler.mjs +18 -5
  102. package/lib/core/handlers/WebSocketHandler.mjs.map +1 -1
  103. package/lib/core/http.d.mts +1 -1
  104. package/lib/core/http.d.ts +1 -1
  105. package/lib/core/index.d.mts +7 -12
  106. package/lib/core/index.d.ts +7 -12
  107. package/lib/core/index.js +2 -2
  108. package/lib/core/index.js.map +1 -1
  109. package/lib/core/index.mjs +1 -1
  110. package/lib/core/index.mjs.map +1 -1
  111. package/lib/core/network-frame-B7A0ggXE.d.mts +56 -0
  112. package/lib/core/network-frame-usYiHS0K.d.ts +56 -0
  113. package/lib/core/passthrough.d.mts +1 -1
  114. package/lib/core/passthrough.d.ts +1 -1
  115. package/lib/core/sharedOptions.d.mts +6 -2
  116. package/lib/core/sharedOptions.d.ts +6 -2
  117. package/lib/core/sharedOptions.js.map +1 -1
  118. package/lib/core/sse.d.mts +1 -1
  119. package/lib/core/sse.d.ts +1 -1
  120. package/lib/core/sse.js.map +1 -1
  121. package/lib/core/sse.mjs.map +1 -1
  122. package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
  123. package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
  124. package/lib/core/utils/cookieStore.js.map +1 -1
  125. package/lib/core/utils/cookieStore.mjs.map +1 -1
  126. package/lib/core/utils/executeHandlers.d.mts +1 -1
  127. package/lib/core/utils/executeHandlers.d.ts +1 -1
  128. package/lib/core/utils/handleRequest.d.mts +2 -1
  129. package/lib/core/utils/handleRequest.d.ts +2 -1
  130. package/lib/core/utils/internal/isHandlerKind.d.mts +3 -3
  131. package/lib/core/utils/internal/isHandlerKind.d.ts +3 -3
  132. package/lib/core/utils/internal/isHandlerKind.js +2 -1
  133. package/lib/core/utils/internal/isHandlerKind.js.map +1 -1
  134. package/lib/core/utils/internal/isHandlerKind.mjs +2 -1
  135. package/lib/core/utils/internal/isHandlerKind.mjs.map +1 -1
  136. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +1 -1
  137. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +1 -1
  138. package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
  139. package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
  140. package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
  141. package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
  142. package/lib/core/utils/matching/matchRequestUrl.js +1 -1
  143. package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
  144. package/lib/core/utils/matching/matchRequestUrl.mjs +1 -1
  145. package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
  146. package/lib/core/utils/request/onUnhandledRequest.d.mts +2 -2
  147. package/lib/core/utils/request/onUnhandledRequest.d.ts +2 -2
  148. package/lib/core/utils/request/onUnhandledRequest.js.map +1 -1
  149. package/lib/core/utils/request/onUnhandledRequest.mjs.map +1 -1
  150. package/lib/core/ws/handleWebSocketEvent.d.mts +1 -1
  151. package/lib/core/ws/handleWebSocketEvent.d.ts +1 -1
  152. package/lib/core/ws/handleWebSocketEvent.js +1 -1
  153. package/lib/core/ws/handleWebSocketEvent.js.map +1 -1
  154. package/lib/core/ws/handleWebSocketEvent.mjs +1 -1
  155. package/lib/core/ws/handleWebSocketEvent.mjs.map +1 -1
  156. package/lib/core/ws/utils/attachWebSocketLogger.d.mts +1 -1
  157. package/lib/core/ws/utils/attachWebSocketLogger.d.ts +1 -1
  158. package/lib/core/ws/utils/attachWebSocketLogger.js +39 -10
  159. package/lib/core/ws/utils/attachWebSocketLogger.js.map +1 -1
  160. package/lib/core/ws/utils/attachWebSocketLogger.mjs +39 -10
  161. package/lib/core/ws/utils/attachWebSocketLogger.mjs.map +1 -1
  162. package/lib/core/ws.d.mts +3 -3
  163. package/lib/core/ws.d.ts +3 -3
  164. package/lib/core/ws.js.map +1 -1
  165. package/lib/core/ws.mjs.map +1 -1
  166. package/lib/iife/index.js +2022 -1433
  167. package/lib/iife/index.js.map +1 -1
  168. package/lib/mockServiceWorker.js +1 -1
  169. package/lib/native/index.d.mts +21 -29
  170. package/lib/native/index.d.ts +21 -29
  171. package/lib/native/index.js +48 -116
  172. package/lib/native/index.js.map +1 -1
  173. package/lib/native/index.mjs +51 -118
  174. package/lib/native/index.mjs.map +1 -1
  175. package/lib/node/index.d.mts +55 -33
  176. package/lib/node/index.d.ts +55 -33
  177. package/lib/node/index.js +152 -154
  178. package/lib/node/index.js.map +1 -1
  179. package/lib/node/index.mjs +156 -156
  180. package/lib/node/index.mjs.map +1 -1
  181. package/package.json +10 -2
  182. package/src/browser/{setupWorker/glossary.ts → glossary.ts} +16 -33
  183. package/src/browser/index.ts +2 -3
  184. package/src/browser/{setupWorker/setupWorker.node.test.ts → setup-worker.node.test.ts} +2 -4
  185. package/src/browser/setup-worker.ts +148 -0
  186. package/src/browser/sources/fallback-http-source.ts +56 -0
  187. package/src/browser/sources/service-worker-source.ts +455 -0
  188. package/src/browser/tsconfig.browser.json +7 -2
  189. package/src/browser/utils/deserializeRequest.ts +1 -1
  190. package/src/browser/{setupWorker/start/utils/getWorkerByRegistration.ts → utils/get-worker-by-registration.ts} +3 -1
  191. package/src/browser/{setupWorker/start/utils/getWorkerInstance.ts → utils/get-worker-instance.ts} +4 -4
  192. package/src/browser/utils/pruneGetRequestBody.test.ts +1 -3
  193. package/src/browser/utils/pruneGetRequestBody.ts +1 -1
  194. package/src/browser/utils/validate-worker-scope.ts +19 -0
  195. package/src/browser/utils/workerChannel.ts +2 -2
  196. package/src/core/experimental/compat.ts +50 -0
  197. package/src/core/experimental/define-network.test.ts +124 -0
  198. package/src/core/experimental/define-network.ts +215 -0
  199. package/src/core/experimental/frames/http-frame.test.ts +360 -0
  200. package/src/core/experimental/frames/http-frame.ts +271 -0
  201. package/src/core/experimental/frames/network-frame.ts +64 -0
  202. package/src/core/experimental/frames/websocket-frame.test.ts +280 -0
  203. package/src/core/experimental/frames/websocket-frame.ts +188 -0
  204. package/src/core/experimental/handlers-controller.test.ts +198 -0
  205. package/src/core/experimental/handlers-controller.ts +145 -0
  206. package/src/core/experimental/index.ts +16 -0
  207. package/src/core/experimental/on-unhandled-frame.test.ts +360 -0
  208. package/src/core/experimental/on-unhandled-frame.ts +110 -0
  209. package/src/core/experimental/request-utils.test.ts +70 -0
  210. package/src/core/experimental/request-utils.ts +39 -0
  211. package/src/core/experimental/setup-api.ts +59 -0
  212. package/src/core/experimental/sources/interceptor-source.ts +185 -0
  213. package/src/core/experimental/sources/network-source.test.ts +74 -0
  214. package/src/core/experimental/sources/network-source.ts +56 -0
  215. package/src/core/handlers/RequestHandler.ts +9 -10
  216. package/src/core/handlers/WebSocketHandler.ts +27 -11
  217. package/src/core/index.ts +3 -7
  218. package/src/core/sharedOptions.ts +9 -4
  219. package/src/core/sse.ts +1 -1
  220. package/src/core/utils/cookieStore.ts +2 -1
  221. package/src/core/utils/internal/isHandlerKind.test.ts +20 -22
  222. package/src/core/utils/internal/isHandlerKind.ts +5 -9
  223. package/src/core/utils/matching/matchRequestUrl.test.ts +87 -3
  224. package/src/core/utils/matching/matchRequestUrl.ts +2 -2
  225. package/src/core/utils/request/onUnhandledRequest.ts +2 -2
  226. package/src/core/ws/WebSocketClientManager.test.ts +2 -10
  227. package/src/core/ws/handleWebSocketEvent.ts +5 -1
  228. package/src/core/ws/utils/attachWebSocketLogger.ts +43 -11
  229. package/src/core/ws.test.ts +1 -3
  230. package/src/core/ws.ts +6 -6
  231. package/src/iife/index.ts +1 -1
  232. package/src/native/index.ts +34 -11
  233. package/src/node/async-handlers-controller.test.ts +50 -0
  234. package/src/node/async-handlers-controller.ts +69 -0
  235. package/src/node/glossary.ts +19 -18
  236. package/src/node/index.ts +6 -2
  237. package/src/node/setup-server-common.ts +100 -0
  238. package/src/node/setup-server.ts +91 -0
  239. package/src/tsconfig.core.json +8 -0
  240. package/src/tsconfig.node.json +8 -3
  241. package/src/tsconfig.src.json +0 -2
  242. package/src/tsconfig.worker.json +2 -1
  243. package/lib/core/SetupApi.d.mts +0 -44
  244. package/lib/core/SetupApi.d.ts +0 -44
  245. package/lib/core/SetupApi.js +0 -112
  246. package/lib/core/SetupApi.js.map +0 -1
  247. package/lib/core/SetupApi.mjs +0 -92
  248. package/lib/core/SetupApi.mjs.map +0 -1
  249. package/lib/core/handlers/common.d.mts +0 -3
  250. package/lib/core/handlers/common.d.ts +0 -3
  251. package/lib/core/handlers/common.js.map +0 -1
  252. package/lib/core/handlers/common.mjs +0 -1
  253. package/lib/core/handlers/common.mjs.map +0 -1
  254. package/src/browser/setupWorker/setupWorker.ts +0 -184
  255. package/src/browser/setupWorker/start/createFallbackRequestListener.ts +0 -71
  256. package/src/browser/setupWorker/start/createRequestListener.ts +0 -138
  257. package/src/browser/setupWorker/start/createResponseListener.ts +0 -57
  258. package/src/browser/setupWorker/start/createStartHandler.ts +0 -137
  259. package/src/browser/setupWorker/start/utils/enableMocking.ts +0 -30
  260. package/src/browser/setupWorker/start/utils/prepareStartHandler.test.ts +0 -59
  261. package/src/browser/setupWorker/start/utils/prepareStartHandler.ts +0 -44
  262. package/src/browser/setupWorker/start/utils/printStartMessage.test.ts +0 -84
  263. package/src/browser/setupWorker/start/utils/printStartMessage.ts +0 -51
  264. package/src/browser/setupWorker/start/utils/validateWorkerScope.ts +0 -18
  265. package/src/browser/setupWorker/stop/utils/printStopMessage.test.ts +0 -26
  266. package/src/browser/setupWorker/stop/utils/printStopMessage.ts +0 -13
  267. package/src/browser/utils/checkWorkerIntegrity.ts +0 -42
  268. package/src/core/SetupApi.ts +0 -127
  269. package/src/core/handlers/common.ts +0 -1
  270. package/src/node/SetupServerApi.ts +0 -87
  271. package/src/node/SetupServerCommonApi.ts +0 -169
  272. package/src/node/setupServer.ts +0 -15
@@ -0,0 +1,39 @@
1
+ export const REQUEST_INTENTION_HEADER_NAME = 'x-msw-intention'
2
+
3
+ export enum RequestIntention {
4
+ passthrough = 'passthrough',
5
+ }
6
+
7
+ export function shouldBypassRequest(request: Request): boolean {
8
+ return !!request.headers.get('accept')?.includes('msw/passthrough')
9
+ }
10
+
11
+ export function isPassthroughResponse(response: Response): boolean {
12
+ return (
13
+ response.status === 302 &&
14
+ response.headers.get(REQUEST_INTENTION_HEADER_NAME) ===
15
+ RequestIntention.passthrough
16
+ )
17
+ }
18
+
19
+ /**
20
+ * Remove the internal passthrough instruction from the request's `Accept` header.
21
+ */
22
+ export function deleteRequestPassthroughHeader(request: Request): void {
23
+ const acceptHeader = request.headers.get('accept')
24
+
25
+ /**
26
+ * @note Remove the internal bypass request header.
27
+ * In the browser, this is done by the worker script.
28
+ * In Node.js, it has to be done here.
29
+ */
30
+ if (acceptHeader) {
31
+ const nextAcceptHeader = acceptHeader.replace(/(,\s+)?msw\/passthrough/, '')
32
+
33
+ if (nextAcceptHeader) {
34
+ request.headers.set('accept', nextAcceptHeader)
35
+ } else {
36
+ request.headers.delete('accept')
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,59 @@
1
+ import { type DefaultEventMap, Emitter } from 'rettime'
2
+ import { LifeCycleEventEmitter } from '../sharedOptions'
3
+ import {
4
+ AnyHandler,
5
+ HandlersController,
6
+ InMemoryHandlersController,
7
+ } from './handlers-controller'
8
+ import { Disposable } from '../utils/internal/Disposable'
9
+ import { toReadonlyArray } from '../utils/internal/toReadonlyArray'
10
+
11
+ /**
12
+ * Generic class for the mock API setup.
13
+ * Preserved only for backward compatibility.
14
+ * @deprecated
15
+ */
16
+ export abstract class SetupApi<
17
+ EventMap extends DefaultEventMap,
18
+ > extends Disposable {
19
+ protected handlersController: HandlersController
20
+ protected emitter: Emitter<EventMap>
21
+ protected publicEmitter: Emitter<EventMap>
22
+
23
+ public readonly events: LifeCycleEventEmitter<EventMap>
24
+
25
+ constructor(...initialHandlers: Array<AnyHandler>) {
26
+ super()
27
+
28
+ this.handlersController = new InMemoryHandlersController(initialHandlers)
29
+
30
+ this.emitter = new Emitter()
31
+ this.publicEmitter = new Emitter()
32
+ this.events = this.emitter
33
+
34
+ this.subscriptions.push(() => {
35
+ this.emitter.removeAllListeners()
36
+ this.publicEmitter.removeAllListeners()
37
+ })
38
+ }
39
+
40
+ public use(...runtimeHandlers: Array<AnyHandler>): void {
41
+ this.handlersController.use(runtimeHandlers)
42
+ }
43
+
44
+ public restoreHandlers(): void {
45
+ this.handlersController.currentHandlers().forEach((handler) => {
46
+ if ('isUsed' in handler) {
47
+ handler.isUsed = false
48
+ }
49
+ })
50
+ }
51
+
52
+ public resetHandlers(...nextHandlers: Array<AnyHandler>): void {
53
+ this.handlersController.reset(nextHandlers)
54
+ }
55
+
56
+ public listHandlers(): ReadonlyArray<AnyHandler> {
57
+ return toReadonlyArray(this.handlersController.currentHandlers())
58
+ }
59
+ }
@@ -0,0 +1,185 @@
1
+ import {
2
+ BatchInterceptor,
3
+ Interceptor,
4
+ RequestController,
5
+ type HttpRequestEventMap,
6
+ } from '@mswjs/interceptors'
7
+ import type {
8
+ WebSocketConnectionData,
9
+ WebSocketEventMap,
10
+ } from '@mswjs/interceptors/WebSocket'
11
+ import { NetworkSource } from './network-source'
12
+ import { InternalError } from '../../utils/internal/devUtils'
13
+ import { HttpNetworkFrame, ResponseEvent } from '../frames/http-frame'
14
+ import { WebSocketNetworkFrame } from '../frames/websocket-frame'
15
+ import { deleteRequestPassthroughHeader } from '../request-utils'
16
+
17
+ export interface InterceptorSourceOptions {
18
+ interceptors: Array<Interceptor<HttpRequestEventMap | WebSocketEventMap>>
19
+ }
20
+
21
+ /**
22
+ * Create a network source from the given list of interceptors.
23
+ */
24
+ export class InterceptorSource extends NetworkSource {
25
+ #interceptor: BatchInterceptor<
26
+ InterceptorSourceOptions['interceptors'],
27
+ HttpRequestEventMap | WebSocketEventMap
28
+ >
29
+
30
+ #frames: Map<string, HttpNetworkFrame>
31
+
32
+ constructor(options: InterceptorSourceOptions) {
33
+ super()
34
+
35
+ this.#interceptor = new BatchInterceptor({
36
+ name: 'interceptor-source',
37
+ interceptors: options.interceptors,
38
+ })
39
+ this.#frames = new Map()
40
+ }
41
+
42
+ public enable(): void {
43
+ this.#interceptor.apply()
44
+
45
+ /**
46
+ * @todo @fixme BatchInterceptor infers event types but not listener types.
47
+ */
48
+ this.#interceptor
49
+ .on('request', this.#handleRequest.bind(this) as any)
50
+ .on('response', this.#handleResponse.bind(this) as any)
51
+ .on('connection', this.#handleWebSocketConnection.bind(this) as any)
52
+ }
53
+
54
+ public disable(): void {
55
+ super.disable()
56
+ this.#interceptor.dispose()
57
+
58
+ /**
59
+ * @todo We can also abort any pending frames here, given we implement
60
+ * the `NetworkFrame.abort()` method.
61
+ */
62
+ this.#frames.clear()
63
+ }
64
+
65
+ async #handleRequest({
66
+ requestId,
67
+ request,
68
+ controller,
69
+ }: HttpRequestEventMap['request'][0]): Promise<void> {
70
+ const httpFrame = new InterceptorHttpNetworkFrame({
71
+ id: requestId,
72
+ request,
73
+ controller,
74
+ })
75
+
76
+ this.#frames.set(requestId, httpFrame)
77
+ await this.queue(httpFrame)
78
+ }
79
+
80
+ async #handleResponse({
81
+ requestId,
82
+ request,
83
+ response,
84
+ isMockedResponse,
85
+ }: HttpRequestEventMap['response'][0]): Promise<void> {
86
+ const httpFrame = this.#frames.get(requestId)
87
+ this.#frames.delete(requestId)
88
+
89
+ if (httpFrame == null) {
90
+ return
91
+ }
92
+
93
+ queueMicrotask(() => {
94
+ httpFrame.events.emit(
95
+ new ResponseEvent(
96
+ isMockedResponse ? 'response:mocked' : 'response:bypass',
97
+ {
98
+ requestId,
99
+ request,
100
+ response,
101
+ },
102
+ ),
103
+ )
104
+ })
105
+ }
106
+
107
+ async #handleWebSocketConnection(
108
+ connection: WebSocketEventMap['connection'][0],
109
+ ): Promise<void> {
110
+ await this.queue(
111
+ new InterceptorWebSocketNetworkFrame({
112
+ connection,
113
+ }),
114
+ )
115
+ }
116
+ }
117
+
118
+ class InterceptorHttpNetworkFrame extends HttpNetworkFrame {
119
+ #controller: RequestController
120
+
121
+ constructor(options: {
122
+ id: string
123
+ request: Request
124
+ controller: RequestController
125
+ }) {
126
+ super({
127
+ id: options.id,
128
+ request: options.request,
129
+ })
130
+
131
+ this.#controller = options.controller
132
+ }
133
+
134
+ public passthrough(): void {
135
+ deleteRequestPassthroughHeader(this.data.request)
136
+ }
137
+
138
+ public respondWith(response?: Response): void {
139
+ if (response) {
140
+ this.#controller.respondWith(response)
141
+ }
142
+ }
143
+
144
+ public errorWith(reason?: unknown): void {
145
+ if (reason instanceof Response) {
146
+ return this.respondWith(reason)
147
+ }
148
+
149
+ if (reason instanceof InternalError) {
150
+ this.#controller.errorWith(reason)
151
+ }
152
+
153
+ throw reason
154
+ }
155
+ }
156
+
157
+ class InterceptorWebSocketNetworkFrame extends WebSocketNetworkFrame {
158
+ constructor(args: { connection: WebSocketConnectionData }) {
159
+ super({ connection: args.connection })
160
+ }
161
+
162
+ public errorWith(reason?: unknown): void {
163
+ if (reason instanceof Error) {
164
+ const { client } = this.data.connection
165
+
166
+ /**
167
+ * Use `client.errorWith(reason)` in the future.
168
+ * @see https://github.com/mswjs/interceptors/issues/747
169
+ */
170
+ const errorEvent = new Event('error')
171
+
172
+ Object.defineProperty(errorEvent, 'cause', {
173
+ enumerable: true,
174
+ configurable: false,
175
+ value: reason,
176
+ })
177
+
178
+ client.socket.dispatchEvent(errorEvent)
179
+ }
180
+ }
181
+
182
+ public passthrough() {
183
+ this.data.connection.server.connect()
184
+ }
185
+ }
@@ -0,0 +1,74 @@
1
+ import { NetworkFrame } from '../frames/network-frame'
2
+ import { NetworkSource } from './network-source'
3
+
4
+ class TestFrame extends NetworkFrame<any, any, any> {
5
+ constructor() {
6
+ super('test', {})
7
+ }
8
+
9
+ getHandlers = () => []
10
+ passthrough = vi.fn()
11
+ errorWith = vi.fn()
12
+ resolve = vi.fn()
13
+ getUnhandledMessage = vi.fn()
14
+ }
15
+
16
+ afterEach(() => {
17
+ vi.clearAllMocks()
18
+ })
19
+
20
+ it('emits the "frame" event when a frame is queued', async () => {
21
+ class CustomNetworkSource extends NetworkSource {
22
+ enable = async () => {}
23
+ }
24
+
25
+ const source = new CustomNetworkSource()
26
+ const frameListener = vi.fn()
27
+ source.on('frame', frameListener)
28
+
29
+ const frame = new TestFrame()
30
+ await expect(source.queue(frame)).resolves.toBeUndefined()
31
+
32
+ expect(frameListener).toHaveBeenCalledExactlyOnceWith(
33
+ expect.objectContaining({ frame }),
34
+ )
35
+ })
36
+
37
+ it('removes all listeners when "disable" is called', async () => {
38
+ class CustomNetworkSource extends NetworkSource {
39
+ enable = async () => {}
40
+ }
41
+
42
+ const source = new CustomNetworkSource()
43
+ const frameListener = vi.fn()
44
+ source.on('frame', frameListener)
45
+
46
+ expect(source.disable()).toBeUndefined()
47
+ await expect(source.queue(new TestFrame())).resolves.toBeUndefined()
48
+
49
+ expect.soft(frameListener).not.toHaveBeenCalled()
50
+ })
51
+
52
+ it('accepts AbortSignal when attaching event listeners', async () => {
53
+ class CustomNetworkSource extends NetworkSource {
54
+ enable = async () => {}
55
+ }
56
+
57
+ const source = new CustomNetworkSource()
58
+ const frame = new TestFrame()
59
+
60
+ const frameListener = vi.fn()
61
+ const controller = new AbortController()
62
+ source.on('frame', frameListener, { signal: controller.signal })
63
+
64
+ await expect(source.queue(frame)).resolves.toBeUndefined()
65
+ expect(frameListener).toHaveBeenCalledExactlyOnceWith(
66
+ expect.objectContaining({ frame }),
67
+ )
68
+
69
+ frameListener.mockClear()
70
+ controller.abort()
71
+
72
+ await expect(source.queue(frame)).resolves.toBeUndefined()
73
+ expect(frameListener).not.toHaveBeenCalled()
74
+ })
@@ -0,0 +1,56 @@
1
+ import { Emitter, TypedEvent, type TypedListenerOptions } from 'rettime'
2
+ import {
3
+ type AnyNetworkFrame,
4
+ type ExtractFrameEvents,
5
+ } from '../frames/network-frame'
6
+
7
+ class NetworkFrameEvent<
8
+ DataType = void,
9
+ ReturnType = void,
10
+ EventType extends string = string,
11
+ > extends TypedEvent<DataType, ReturnType, EventType> {
12
+ public frame: AnyNetworkFrame
13
+
14
+ constructor(type: string, frame: AnyNetworkFrame) {
15
+ super(...([type, {}] as any))
16
+ this.frame = frame
17
+ }
18
+ }
19
+
20
+ type NetworkSourceEventMap<Frame extends AnyNetworkFrame> = {
21
+ frame: NetworkFrameEvent<Frame>
22
+ }
23
+
24
+ export type ExtractSourceEvents<Source> =
25
+ Source extends NetworkSource<infer Frame> ? ExtractFrameEvents<Frame> : never
26
+
27
+ export abstract class NetworkSource<
28
+ Frame extends AnyNetworkFrame = AnyNetworkFrame,
29
+ > {
30
+ protected emitter: Emitter<NetworkSourceEventMap<Frame>>
31
+
32
+ constructor() {
33
+ this.emitter = new Emitter()
34
+ }
35
+
36
+ public abstract enable(): unknown | Promise<unknown>
37
+
38
+ public async queue(frame: Frame): Promise<void> {
39
+ await this.emitter.emitAsPromise(
40
+ // @ts-expect-error Trouble handling a conditional type parameter.
41
+ new NetworkFrameEvent('frame', frame),
42
+ )
43
+ }
44
+
45
+ public on<Type extends keyof NetworkSourceEventMap<Frame>>(
46
+ type: Type,
47
+ listener: Emitter.ListenerType<typeof this.emitter, Type>,
48
+ options?: TypedListenerOptions,
49
+ ): void {
50
+ this.emitter.on(type, listener, options)
51
+ }
52
+
53
+ public disable(): void | Promise<void> {
54
+ this.emitter.removeAllListeners()
55
+ }
56
+ }
@@ -11,7 +11,6 @@ import {
11
11
  HttpResponse,
12
12
  DefaultUnsafeFetchResponse,
13
13
  } from '../HttpResponse'
14
- import type { HandlerKind } from './common'
15
14
  import type { GraphQLRequestBody } from './GraphQLHandler'
16
15
 
17
16
  export type DefaultRequestMultipartBody = Record<
@@ -133,14 +132,7 @@ export abstract class RequestHandler<
133
132
  StrictRequest<DefaultBodyType>
134
133
  >()
135
134
 
136
- private readonly __kind: HandlerKind
137
-
138
- public info: HandlerInfo & RequestHandlerInternalInfo
139
- /**
140
- * Indicates whether this request handler has been used
141
- * (its resolver has successfully executed).
142
- */
143
- public isUsed: boolean
135
+ public readonly kind = 'request' as const
144
136
 
145
137
  protected resolver: ResponseResolver<ResolverExtras, any, any>
146
138
  private resolverIterator?:
@@ -157,6 +149,14 @@ export abstract class RequestHandler<
157
149
  private resolverIteratorResult?: Response | HttpResponse<any>
158
150
  private options?: HandlerOptions
159
151
 
152
+ public info: HandlerInfo & RequestHandlerInternalInfo
153
+
154
+ /**
155
+ * Indicates whether this request handler has been used
156
+ * (its resolver has successfully executed).
157
+ */
158
+ public isUsed: boolean
159
+
160
160
  constructor(args: RequestHandlerArgs<HandlerInfo, HandlerOptions>) {
161
161
  this.resolver = args.resolver
162
162
  this.options = args.options
@@ -169,7 +169,6 @@ export abstract class RequestHandler<
169
169
  }
170
170
 
171
171
  this.isUsed = false
172
- this.__kind = 'RequestHandler'
173
172
  }
174
173
 
175
174
  /**
@@ -12,7 +12,7 @@ import {
12
12
  matchRequestUrl,
13
13
  } from '../utils/matching/matchRequestUrl'
14
14
  import { getCallFrame } from '../utils/internal/getCallFrame'
15
- import type { HandlerKind } from './common'
15
+ import { attachWebSocketLogger } from '../ws/utils/attachWebSocketLogger'
16
16
 
17
17
  type WebSocketHandlerParsedResult = {
18
18
  match: Match
@@ -31,18 +31,21 @@ export interface WebSocketHandlerConnection {
31
31
 
32
32
  export interface WebSocketResolutionContext {
33
33
  baseUrl?: string
34
+ [kAutoConnect]?: boolean
34
35
  }
35
36
 
36
37
  export const kEmitter = Symbol('kEmitter')
37
38
  export const kSender = Symbol('kSender')
39
+ export const kConnect = Symbol('kConnect')
40
+ export const kAutoConnect = Symbol('kAutoConnect')
41
+
38
42
  const kStopPropagationPatched = Symbol('kStopPropagationPatched')
39
43
  const KOnStopPropagation = Symbol('KOnStopPropagation')
40
44
 
41
45
  export class WebSocketHandler {
42
- private readonly __kind: HandlerKind
43
-
44
46
  public id: string
45
47
  public callFrame?: string
48
+ public kind = 'websocket' as const
46
49
 
47
50
  protected [kEmitter]: Emitter<WebSocketHandlerEventMap>
48
51
 
@@ -51,7 +54,6 @@ export class WebSocketHandler {
51
54
 
52
55
  this[kEmitter] = new Emitter()
53
56
  this.callFrame = getCallFrame(new Error())
54
- this.__kind = 'EventHandler'
55
57
  }
56
58
 
57
59
  public parse(args: {
@@ -95,16 +97,16 @@ export class WebSocketHandler {
95
97
  }
96
98
 
97
99
  public async run(
98
- connection: Omit<WebSocketHandlerConnection, 'params'>,
100
+ connection: WebSocketConnectionData,
99
101
  resolutionContext?: WebSocketResolutionContext,
100
- ): Promise<boolean> {
102
+ ): Promise<WebSocketHandlerConnection | null> {
101
103
  const parsedResult = this.parse({
102
104
  url: connection.client.url,
103
105
  resolutionContext,
104
106
  })
105
107
 
106
108
  if (!this.predicate({ url: connection.client.url, parsedResult })) {
107
- return false
109
+ return null
108
110
  }
109
111
 
110
112
  const resolvedConnection: WebSocketHandlerConnection = {
@@ -112,10 +114,18 @@ export class WebSocketHandler {
112
114
  params: parsedResult.match.params || {},
113
115
  }
114
116
 
115
- return this.connect(resolvedConnection)
117
+ if (resolutionContext?.[kAutoConnect]) {
118
+ if (this[kConnect](resolvedConnection)) {
119
+ return resolvedConnection
120
+ }
121
+
122
+ return null
123
+ }
124
+
125
+ return resolvedConnection
116
126
  }
117
127
 
118
- protected connect(connection: WebSocketHandlerConnection): boolean {
128
+ protected [kConnect](connection: WebSocketHandlerConnection): boolean {
119
129
  // Support `event.stopPropagation()` for various client/server events.
120
130
  connection.client.addEventListener(
121
131
  'message',
@@ -143,11 +153,17 @@ export class WebSocketHandler {
143
153
  createStopPropagationListener(this),
144
154
  )
145
155
 
146
- // Emit the connection event on the handler.
147
- // This is what the developer adds listeners for.
156
+ /**
157
+ * @fixme Use "rettime" and await these events to have
158
+ * exceptions propagate properly.
159
+ */
148
160
  return this[kEmitter].emit('connection', connection)
149
161
  }
150
162
 
163
+ public log(connection: WebSocketConnectionData): () => void {
164
+ return attachWebSocketLogger(connection)
165
+ }
166
+
151
167
  #resolveWebSocketUrl(url: string, baseUrl?: string): string {
152
168
  const resolvedUrl = resolveWebSocketUrl(
153
169
  baseUrl
package/src/core/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { checkGlobals } from './utils/internal/checkGlobals'
2
2
 
3
- export { SetupApi } from './SetupApi'
3
+ export { SetupApi } from './experimental/setup-api'
4
4
 
5
5
  /* HTTP handlers */
6
6
  export { RequestHandler } from './handlers/RequestHandler'
@@ -26,12 +26,6 @@ export {
26
26
  type ServerSentEventMessage,
27
27
  } from './sse'
28
28
 
29
- import type { HttpHandler } from './handlers/HttpHandler'
30
- import type { GraphQLHandler } from './handlers/GraphQLHandler'
31
- import type { WebSocketHandler } from './handlers/WebSocketHandler'
32
-
33
- export type AnyHandler = HttpHandler | GraphQLHandler | WebSocketHandler
34
-
35
29
  /* Utils */
36
30
  export { matchRequestUrl } from './utils/matching/matchRequestUrl'
37
31
  export { handleRequest, type HandleRequestOptions } from './utils/handleRequest'
@@ -47,6 +41,8 @@ export { cleanUrl } from './utils/url/cleanUrl'
47
41
  * Type definitions.
48
42
  */
49
43
 
44
+ export type { AnyHandler } from './experimental/handlers-controller'
45
+
50
46
  export type { SharedOptions, LifeCycleEventsMap } from './sharedOptions'
51
47
 
52
48
  export type {
@@ -1,4 +1,4 @@
1
- import type { Emitter } from 'strict-event-emitter'
1
+ import type { Emitter, DefaultEventMap } from 'rettime'
2
2
  import type { UnhandledRequestStrategy } from './utils/request/onUnhandledRequest'
3
3
 
4
4
  export interface SharedOptions {
@@ -13,6 +13,10 @@ export interface SharedOptions {
13
13
  onUnhandledRequest?: UnhandledRequestStrategy
14
14
  }
15
15
 
16
+ /**
17
+ * @deprecated
18
+ * Please use `HttpNetworkFrameEventMap` or `WebSocketNetworkFrameEventMap` instead.
19
+ */
16
20
  export type LifeCycleEventsMap = {
17
21
  'request:start': [
18
22
  args: {
@@ -61,6 +65,7 @@ export type LifeCycleEventsMap = {
61
65
  ]
62
66
  }
63
67
 
64
- export type LifeCycleEventEmitter<
65
- EventsMap extends Record<string | symbol, any>,
66
- > = Pick<Emitter<EventsMap>, 'on' | 'removeListener' | 'removeAllListeners'>
68
+ export type LifeCycleEventEmitter<EventMap extends DefaultEventMap> = Pick<
69
+ Emitter<EventMap>,
70
+ 'on' | 'removeListener' | 'removeAllListeners'
71
+ >
package/src/core/sse.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  type HttpRequestResolverExtras,
7
7
  type HttpRequestParsedResult,
8
8
  } from './handlers/HttpHandler'
9
- import type { ResponseResolutionContext } from '~/core/utils/executeHandlers'
9
+ import type { ResponseResolutionContext } from '#core/utils/executeHandlers'
10
10
  import type { Path, PathParams } from './utils/matching/matchRequestUrl'
11
11
  import { delay } from './delay'
12
12
  import { getTimestamp } from './utils/logging/getTimestamp'
@@ -4,6 +4,7 @@ import {
4
4
  Cookie,
5
5
  CookieJar,
6
6
  MemoryCookieStore,
7
+ SerializedCookie,
7
8
  type MemoryCookieStoreIndex,
8
9
  } from 'tough-cookie'
9
10
  import { jsonParse } from './internal/jsonParse'
@@ -76,7 +77,7 @@ class CookieStore {
76
77
  return
77
78
  }
78
79
 
79
- const data = []
80
+ const data: Array<SerializedCookie> = []
80
81
  const { idx } = this.#memoryStore
81
82
 
82
83
  for (const domain in idx) {