msw 2.14.7 → 3.0.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 (759) hide show
  1. package/README.md +8 -0
  2. package/cli/init.js +12 -9
  3. package/cli/invariant.js +2 -2
  4. package/lib/_chunks/attach-sibling-handlers.js +360 -0
  5. package/lib/_chunks/attach-sibling-handlers.js.map +1 -0
  6. package/lib/_chunks/colors.js +18 -0
  7. package/lib/_chunks/colors.js.map +1 -0
  8. package/lib/_chunks/cookie-store.js +348 -0
  9. package/lib/_chunks/cookie-store.js.map +1 -0
  10. package/lib/_chunks/execute-handlers.js +29 -0
  11. package/lib/_chunks/execute-handlers.js.map +1 -0
  12. package/lib/_chunks/handlers-controller.d.ts +262 -0
  13. package/lib/_chunks/has-ref-counted.js +9 -0
  14. package/lib/_chunks/has-ref-counted.js.map +1 -0
  15. package/lib/_chunks/http-handler.d.ts +72 -0
  16. package/lib/_chunks/http-handler.js +182 -0
  17. package/lib/_chunks/http-handler.js.map +1 -0
  18. package/lib/_chunks/http-response.js +137 -0
  19. package/lib/_chunks/http-response.js.map +1 -0
  20. package/lib/{core → _chunks}/http.d.ts +15 -18
  21. package/lib/_chunks/http.js +30 -0
  22. package/lib/_chunks/http.js.map +1 -0
  23. package/lib/_chunks/interceptor-source.d.ts +163 -0
  24. package/lib/_chunks/interceptor-source.js +756 -0
  25. package/lib/_chunks/interceptor-source.js.map +1 -0
  26. package/lib/_chunks/is-object.js +11 -0
  27. package/lib/_chunks/is-object.js.map +1 -0
  28. package/lib/_chunks/match-request-url.d.ts +14 -0
  29. package/lib/_chunks/request-handler.d.ts +295 -0
  30. package/lib/_chunks/request-handler.js +369 -0
  31. package/lib/_chunks/request-handler.js.map +1 -0
  32. package/lib/_chunks/shared-options.d.ts +20 -0
  33. package/lib/_chunks/sse.d.ts +95 -0
  34. package/lib/_chunks/sse.js +599 -0
  35. package/lib/_chunks/sse.js.map +1 -0
  36. package/lib/_chunks/symbols.js +22 -0
  37. package/lib/_chunks/symbols.js.map +1 -0
  38. package/lib/_chunks/websocket-upgrade.js +46 -0
  39. package/lib/_chunks/websocket-upgrade.js.map +1 -0
  40. package/lib/_chunks/ws.d.ts +133 -0
  41. package/lib/_chunks/ws.js +293 -0
  42. package/lib/_chunks/ws.js.map +1 -0
  43. package/lib/browser/index.d.ts +225 -96
  44. package/lib/browser/index.js +555 -3694
  45. package/lib/browser/index.js.map +1 -1
  46. package/lib/core/experimental/index.d.ts +3 -17
  47. package/lib/core/experimental/index.js +2 -38
  48. package/lib/core/index.d.ts +15 -27
  49. package/lib/core/index.js +15 -64
  50. package/lib/graphql/index.d.ts +550 -0
  51. package/lib/graphql/index.js +1244 -0
  52. package/lib/graphql/index.js.map +1 -0
  53. package/lib/http/index.d.ts +4 -0
  54. package/lib/http/index.js +4 -0
  55. package/lib/iife/index.js +35857 -28289
  56. package/lib/iife/index.js.map +1 -1
  57. package/lib/mockServiceWorker.js +204 -93
  58. package/lib/node/index.d.ts +79 -104
  59. package/lib/node/index.js +103 -201
  60. package/lib/node/index.js.map +1 -1
  61. package/lib/sse/index.d.ts +2 -0
  62. package/lib/sse/index.js +2 -0
  63. package/lib/{core → utils}/bypass.d.ts +5 -4
  64. package/lib/utils/bypass.js +41 -0
  65. package/lib/utils/bypass.js.map +1 -0
  66. package/lib/utils/delay.d.ts +15 -0
  67. package/lib/utils/delay.js +45 -0
  68. package/lib/utils/delay.js.map +1 -0
  69. package/lib/utils/get-clean-url-string.d.ts +9 -0
  70. package/lib/utils/get-clean-url-string.js +15 -0
  71. package/lib/utils/get-clean-url-string.js.map +1 -0
  72. package/lib/utils/get-response.d.ts +13 -0
  73. package/lib/utils/get-response.js +23 -0
  74. package/lib/utils/get-response.js.map +1 -0
  75. package/lib/utils/is-common-asset-request.d.ts +22 -0
  76. package/lib/utils/is-common-asset-request.js +31 -0
  77. package/lib/utils/is-common-asset-request.js.map +1 -0
  78. package/lib/utils/passthrough.d.ts +31 -0
  79. package/lib/utils/passthrough.js +41 -0
  80. package/lib/utils/passthrough.js.map +1 -0
  81. package/lib/vite/index.d.ts +44 -0
  82. package/lib/vite/index.js +90 -0
  83. package/lib/vite/index.js.map +1 -0
  84. package/lib/vite/runtime.d.ts +6 -0
  85. package/lib/vite/runtime.js +77 -0
  86. package/lib/vite/runtime.js.map +1 -0
  87. package/lib/ws/index.d.ts +4 -0
  88. package/lib/ws/index.js +4 -0
  89. package/package.json +93 -201
  90. package/src/browser/default-network-options.ts +31 -0
  91. package/src/browser/glossary.ts +11 -23
  92. package/src/browser/index.ts +5 -1
  93. package/src/browser/setup-worker.ts +15 -68
  94. package/src/browser/sources/fallback-http-source.ts +1 -1
  95. package/src/browser/sources/service-worker-source.ts +76 -69
  96. package/src/browser/tsconfig.browser.json +4 -2
  97. package/src/browser/utils/{deserializeRequest.ts → deserialize-request.ts} +3 -4
  98. package/src/browser/utils/{getAbsoluteWorkerUrl.test.ts → get-absolute-worker-url.test.ts} +3 -3
  99. package/src/browser/utils/get-worker-instance.ts +2 -2
  100. package/src/browser/utils/should-invalidate-worker.test.ts +11 -11
  101. package/src/browser/utils/should-invalidate-worker.ts +1 -1
  102. package/src/browser/utils/validate-worker-scope.ts +1 -1
  103. package/src/browser/utils/{workerChannel.ts → worker-channel.ts} +42 -20
  104. package/src/core/experimental/define-network.test.ts +43 -8
  105. package/src/core/experimental/define-network.ts +32 -13
  106. package/src/core/experimental/frames/http-frame.test.ts +15 -13
  107. package/src/core/experimental/frames/http-frame.ts +10 -9
  108. package/src/core/experimental/frames/websocket-frame.test.ts +129 -15
  109. package/src/core/experimental/frames/websocket-frame.ts +71 -20
  110. package/src/core/experimental/handlers-controller.test.ts +141 -34
  111. package/src/core/experimental/handlers-controller.ts +107 -30
  112. package/src/core/experimental/index.ts +1 -0
  113. package/src/core/experimental/on-unhandled-frame.test.ts +19 -19
  114. package/src/core/experimental/on-unhandled-frame.ts +7 -12
  115. package/src/core/experimental/request-utils.test.ts +4 -29
  116. package/src/core/experimental/request-utils.ts +0 -14
  117. package/src/core/experimental/sources/interceptor-source.ts +44 -29
  118. package/src/core/experimental/sources/network-source.test.ts +3 -3
  119. package/src/core/experimental/sources/network-source.ts +3 -3
  120. package/src/core/handlers/handler.ts +42 -0
  121. package/src/core/handlers/{RequestHandler.ts → request-handler.ts} +168 -73
  122. package/src/core/index.ts +35 -58
  123. package/src/core/shared-options.ts +21 -0
  124. package/src/core/type-utils.ts +18 -0
  125. package/src/core/utils/{cookieStore.ts → cookie-store.ts} +14 -9
  126. package/src/core/utils/{executeHandlers.ts → execute-handlers.ts} +2 -2
  127. package/src/core/utils/http-status-messages.ts +69 -0
  128. package/src/core/utils/internal/{attachSiblingHandlers.ts → attach-sibling-handlers.ts} +20 -0
  129. package/src/core/utils/internal/{devUtils.test.ts → dev-utils.test.ts} +3 -3
  130. package/src/core/utils/internal/{Disposable.ts → disposable.ts} +1 -1
  131. package/src/core/utils/internal/{getCallFrame.test.ts → get-call-frame.test.ts} +1 -1
  132. package/src/core/utils/internal/{getCallFrame.ts → get-call-frame.ts} +1 -1
  133. package/src/core/utils/internal/{hasRefCounted.test.ts → has-ref-counted.test.ts} +4 -4
  134. package/src/core/utils/internal/{hasRefCounted.ts → has-ref-counted.ts} +1 -1
  135. package/src/core/utils/internal/{isIterable.test.ts → is-iterable.test.ts} +1 -1
  136. package/src/core/utils/internal/is-iterable.ts +16 -0
  137. package/src/core/utils/internal/{isObject.test.ts → is-object.test.ts} +1 -1
  138. package/src/core/utils/internal/{isStringEqual.test.ts → is-string-equal.test.ts} +7 -7
  139. package/src/core/utils/internal/{jsonParse.test.ts → json-parse.test.ts} +1 -1
  140. package/src/core/utils/internal/observe-response-body-stream.test.ts +64 -0
  141. package/src/core/utils/internal/observe-response-body-stream.ts +76 -0
  142. package/src/core/utils/internal/{parseMultipartData.test.ts → parse-multipart-data.test.ts} +1 -1
  143. package/src/core/utils/internal/{parseMultipartData.ts → parse-multipart-data.ts} +1 -1
  144. package/src/core/utils/internal/{toReadonlyArray.test.ts → to-readonly-array.test.ts} +4 -4
  145. package/src/core/utils/logging/colors.ts +13 -0
  146. package/src/core/utils/logging/{getStatusCodeColor.test.ts → get-status-code-color.test.ts} +1 -1
  147. package/src/core/utils/logging/{getTimestamp.test.ts → get-timestamp.test.ts} +1 -1
  148. package/src/core/utils/logging/{serializeRequest.test.ts → serialize-request.test.ts} +1 -1
  149. package/src/core/utils/logging/{serializeResponse.test.ts → serialize-response.test.ts} +8 -10
  150. package/src/core/utils/logging/{serializeResponse.ts → serialize-response.ts} +2 -4
  151. package/src/core/utils/matching/match-request-url.test.ts +90 -0
  152. package/src/core/utils/matching/match-request-url.ts +45 -0
  153. package/src/core/utils/matching/{normalizePath.node.test.ts → normalize-path.node.test.ts} +2 -4
  154. package/src/core/utils/matching/{normalizePath.test.ts → normalize-path.test.ts} +2 -4
  155. package/src/core/utils/matching/{normalizePath.ts → normalize-path.ts} +8 -5
  156. package/src/core/utils/request/{getAllAcceptedMimeTypes.test.ts → get-all-accepted-mime-types.test.ts} +14 -14
  157. package/src/core/utils/request/get-request-cookies.ts +76 -0
  158. package/src/core/utils/request/store-response-cookies.ts +15 -0
  159. package/src/core/utils/request/{toPublicUrl.node.test.ts → to-public-url.node.test.ts} +1 -1
  160. package/src/core/utils/request/{toPublicUrl.test.ts → to-public-url.test.ts} +2 -2
  161. package/src/core/utils/{HttpResponse/decorators.ts → response-decorators.ts} +28 -9
  162. package/src/core/utils/url/{getAbsoluteUrl.node.test.ts → get-absolute-url.node.test.ts} +5 -7
  163. package/src/core/utils/url/{getAbsoluteUrl.test.ts → get-absolute-url.test.ts} +7 -7
  164. package/src/core/utils/url/{getAbsoluteUrl.ts → get-absolute-url.ts} +1 -1
  165. package/src/core/utils/url/is-absolute-url.test.ts +30 -0
  166. package/src/{core/handlers/GraphQLHandler.test.ts → graphql/graphql-handler.test.ts} +37 -36
  167. package/src/{core/handlers/GraphQLHandler.ts → graphql/graphql-handler.ts} +54 -41
  168. package/src/graphql/graphql-subscription-event.ts +39 -0
  169. package/src/graphql/graphql-subscription.test.ts +208 -0
  170. package/src/graphql/graphql-subscription.ts +1487 -0
  171. package/src/graphql/graphql.test.ts +14 -0
  172. package/src/graphql/graphql.ts +179 -0
  173. package/src/graphql/index.ts +34 -0
  174. package/src/{core/utils/internal/parseGraphQLRequest.test.ts → graphql/parse-graphql-request.test.ts} +47 -6
  175. package/src/{core/utils/internal/parseGraphQLRequest.ts → graphql/parse-graphql-request.ts} +59 -32
  176. package/src/{core/handlers/HttpHandler.test.ts → http/http-handler.test.ts} +107 -18
  177. package/src/{core/handlers/HttpHandler.ts → http/http-handler.ts} +16 -18
  178. package/src/{core/HttpResponse.test.ts → http/http-response.test.ts} +25 -27
  179. package/src/{core/HttpResponse.ts → http/http-response.ts} +15 -17
  180. package/src/{core → http}/http.ts +7 -7
  181. package/src/http/index.test.ts +19 -0
  182. package/src/http/index.ts +22 -0
  183. package/src/http/symbols.ts +19 -0
  184. package/src/iife/index.ts +2 -0
  185. package/src/mockServiceWorker.js +202 -91
  186. package/src/node/async-handlers-controller.test.ts +4 -4
  187. package/src/node/glossary.ts +8 -4
  188. package/src/node/index.ts +1 -6
  189. package/src/node/setup-server-common.ts +16 -73
  190. package/src/node/setup-server.ts +9 -40
  191. package/src/sse/index.test.ts +14 -0
  192. package/src/sse/index.ts +7 -0
  193. package/src/{core → sse}/sse.ts +105 -69
  194. package/src/tsconfig.core.build.json +5 -1
  195. package/src/tsconfig.core.json +8 -1
  196. package/src/tsconfig.node.json +1 -1
  197. package/src/tsconfig.src.json +1 -1
  198. package/src/{core → utils}/bypass.test.ts +22 -5
  199. package/src/{core → utils}/bypass.ts +11 -0
  200. package/src/{core → utils}/delay.ts +5 -5
  201. package/src/utils/get-clean-url-string.test.ts +24 -0
  202. package/src/utils/get-clean-url-string.ts +16 -0
  203. package/src/{core/getResponse.test.ts → utils/get-response.test.ts} +9 -9
  204. package/src/{core/getResponse.ts → utils/get-response.ts} +2 -2
  205. package/src/{core/isCommonAssetRequest.ts → utils/is-common-asset-request.ts} +4 -3
  206. package/src/utils/passthrough.test.ts +41 -0
  207. package/src/utils/passthrough.ts +46 -0
  208. package/src/vite/client.d.ts +16 -0
  209. package/src/vite/index.ts +4 -0
  210. package/src/vite/options.d.ts +5 -0
  211. package/src/vite/plugin.test.ts +918 -0
  212. package/src/vite/plugin.ts +133 -0
  213. package/src/vite/runtime.ts +117 -0
  214. package/src/vite/tsconfig.build.json +7 -0
  215. package/src/ws/index.ts +23 -0
  216. package/src/{core/ws/utils/attachWebSocketLogger.ts → ws/utils/attach-websocket-logger.ts} +45 -23
  217. package/src/{core/ws/utils/getMessageLength.test.ts → ws/utils/get-message-length.test.ts} +4 -4
  218. package/src/{core/ws/utils/getMessageLength.ts → ws/utils/get-message-length.ts} +1 -1
  219. package/src/{core/ws/utils/getPublicData.test.ts → ws/utils/get-public-data.test.ts} +7 -7
  220. package/src/ws/utils/get-public-data.ts +23 -0
  221. package/src/{core/ws/utils/truncateMessage.test.ts → ws/utils/truncate-message.test.ts} +3 -3
  222. package/src/{core/ws/WebSocketClientManager.test.ts → ws/websocket-client-manager.test.ts} +8 -9
  223. package/src/{core/ws/WebSocketClientManager.ts → ws/websocket-client-manager.ts} +24 -28
  224. package/src/{core/ws/WebSocketClientStore.ts → ws/websocket-client-store.ts} +2 -2
  225. package/src/{core/handlers/WebSocketHandler.test.ts → ws/websocket-handler.test.ts} +15 -15
  226. package/src/{core/handlers/WebSocketHandler.ts → ws/websocket-handler.ts} +144 -32
  227. package/src/{core/ws/WebSocketIndexedDBClientStore.ts → ws/websocket-indexeddb-client-store.ts} +12 -13
  228. package/src/{core/ws/WebSocketMemoryClientStore.ts → ws/websocket-memory-client-store.ts} +4 -4
  229. package/src/ws/websocket-upgrade.ts +83 -0
  230. package/src/{core → ws}/ws.test.ts +3 -4
  231. package/src/{core → ws}/ws.ts +106 -53
  232. package/browser/package.json +0 -31
  233. package/cli/package.json +0 -3
  234. package/config/package.json +0 -3
  235. package/config/scripts/postinstall.js +0 -36
  236. package/lib/browser/index.d.mts +0 -112
  237. package/lib/browser/index.mjs +0 -3706
  238. package/lib/browser/index.mjs.map +0 -1
  239. package/lib/core/HttpResponse-BTyqrRB6.d.mts +0 -371
  240. package/lib/core/HttpResponse-BXyXQFMJ.d.ts +0 -371
  241. package/lib/core/HttpResponse.d.mts +0 -6
  242. package/lib/core/HttpResponse.d.ts +0 -6
  243. package/lib/core/HttpResponse.js +0 -176
  244. package/lib/core/HttpResponse.js.map +0 -1
  245. package/lib/core/HttpResponse.mjs +0 -159
  246. package/lib/core/HttpResponse.mjs.map +0 -1
  247. package/lib/core/bypass.d.mts +0 -16
  248. package/lib/core/bypass.js +0 -42
  249. package/lib/core/bypass.js.map +0 -1
  250. package/lib/core/bypass.mjs +0 -22
  251. package/lib/core/bypass.mjs.map +0 -1
  252. package/lib/core/delay.d.mts +0 -18
  253. package/lib/core/delay.d.ts +0 -18
  254. package/lib/core/delay.js +0 -77
  255. package/lib/core/delay.js.map +0 -1
  256. package/lib/core/delay.mjs +0 -57
  257. package/lib/core/delay.mjs.map +0 -1
  258. package/lib/core/experimental/compat.d.mts +0 -17
  259. package/lib/core/experimental/compat.d.ts +0 -17
  260. package/lib/core/experimental/compat.js +0 -55
  261. package/lib/core/experimental/compat.js.map +0 -1
  262. package/lib/core/experimental/compat.mjs +0 -37
  263. package/lib/core/experimental/compat.mjs.map +0 -1
  264. package/lib/core/experimental/define-network.d.mts +0 -75
  265. package/lib/core/experimental/define-network.d.ts +0 -75
  266. package/lib/core/experimental/define-network.js +0 -134
  267. package/lib/core/experimental/define-network.js.map +0 -1
  268. package/lib/core/experimental/define-network.mjs +0 -119
  269. package/lib/core/experimental/define-network.mjs.map +0 -1
  270. package/lib/core/experimental/frames/http-frame.d.mts +0 -77
  271. package/lib/core/experimental/frames/http-frame.d.ts +0 -77
  272. package/lib/core/experimental/frames/http-frame.js +0 -197
  273. package/lib/core/experimental/frames/http-frame.js.map +0 -1
  274. package/lib/core/experimental/frames/http-frame.mjs +0 -181
  275. package/lib/core/experimental/frames/http-frame.mjs.map +0 -1
  276. package/lib/core/experimental/frames/network-frame.d.mts +0 -12
  277. package/lib/core/experimental/frames/network-frame.d.ts +0 -12
  278. package/lib/core/experimental/frames/network-frame.js +0 -35
  279. package/lib/core/experimental/frames/network-frame.js.map +0 -1
  280. package/lib/core/experimental/frames/network-frame.mjs +0 -15
  281. package/lib/core/experimental/frames/network-frame.mjs.map +0 -1
  282. package/lib/core/experimental/frames/websocket-frame.d.mts +0 -55
  283. package/lib/core/experimental/frames/websocket-frame.d.ts +0 -55
  284. package/lib/core/experimental/frames/websocket-frame.js +0 -131
  285. package/lib/core/experimental/frames/websocket-frame.js.map +0 -1
  286. package/lib/core/experimental/frames/websocket-frame.mjs +0 -118
  287. package/lib/core/experimental/frames/websocket-frame.mjs.map +0 -1
  288. package/lib/core/experimental/handlers-controller.d.mts +0 -36
  289. package/lib/core/experimental/handlers-controller.d.ts +0 -36
  290. package/lib/core/experimental/handlers-controller.js +0 -146
  291. package/lib/core/experimental/handlers-controller.js.map +0 -1
  292. package/lib/core/experimental/handlers-controller.mjs +0 -126
  293. package/lib/core/experimental/handlers-controller.mjs.map +0 -1
  294. package/lib/core/experimental/index.d.mts +0 -17
  295. package/lib/core/experimental/index.js.map +0 -1
  296. package/lib/core/experimental/index.mjs +0 -27
  297. package/lib/core/experimental/index.mjs.map +0 -1
  298. package/lib/core/experimental/on-unhandled-frame.d.mts +0 -12
  299. package/lib/core/experimental/on-unhandled-frame.d.ts +0 -12
  300. package/lib/core/experimental/on-unhandled-frame.js +0 -91
  301. package/lib/core/experimental/on-unhandled-frame.js.map +0 -1
  302. package/lib/core/experimental/on-unhandled-frame.mjs +0 -71
  303. package/lib/core/experimental/on-unhandled-frame.mjs.map +0 -1
  304. package/lib/core/experimental/request-utils.d.mts +0 -12
  305. package/lib/core/experimental/request-utils.d.ts +0 -12
  306. package/lib/core/experimental/request-utils.js +0 -50
  307. package/lib/core/experimental/request-utils.js.map +0 -1
  308. package/lib/core/experimental/request-utils.mjs +0 -30
  309. package/lib/core/experimental/request-utils.mjs.map +0 -1
  310. package/lib/core/experimental/setup-api.d.mts +0 -33
  311. package/lib/core/experimental/setup-api.d.ts +0 -33
  312. package/lib/core/experimental/setup-api.js +0 -58
  313. package/lib/core/experimental/setup-api.js.map +0 -1
  314. package/lib/core/experimental/setup-api.mjs +0 -40
  315. package/lib/core/experimental/setup-api.mjs.map +0 -1
  316. package/lib/core/experimental/sources/interceptor-source.d.mts +0 -28
  317. package/lib/core/experimental/sources/interceptor-source.d.ts +0 -28
  318. package/lib/core/experimental/sources/interceptor-source.js +0 -155
  319. package/lib/core/experimental/sources/interceptor-source.js.map +0 -1
  320. package/lib/core/experimental/sources/interceptor-source.mjs +0 -135
  321. package/lib/core/experimental/sources/interceptor-source.mjs.map +0 -1
  322. package/lib/core/experimental/sources/network-source.d.mts +0 -31
  323. package/lib/core/experimental/sources/network-source.d.ts +0 -31
  324. package/lib/core/experimental/sources/network-source.js +0 -51
  325. package/lib/core/experimental/sources/network-source.js.map +0 -1
  326. package/lib/core/experimental/sources/network-source.mjs +0 -32
  327. package/lib/core/experimental/sources/network-source.mjs.map +0 -1
  328. package/lib/core/getResponse.d.mts +0 -18
  329. package/lib/core/getResponse.d.ts +0 -18
  330. package/lib/core/getResponse.js +0 -35
  331. package/lib/core/getResponse.js.map +0 -1
  332. package/lib/core/getResponse.mjs +0 -17
  333. package/lib/core/getResponse.mjs.map +0 -1
  334. package/lib/core/graphql.d.mts +0 -76
  335. package/lib/core/graphql.d.ts +0 -76
  336. package/lib/core/graphql.js +0 -91
  337. package/lib/core/graphql.js.map +0 -1
  338. package/lib/core/graphql.mjs +0 -74
  339. package/lib/core/graphql.mjs.map +0 -1
  340. package/lib/core/handlers/GraphQLHandler.d.mts +0 -6
  341. package/lib/core/handlers/GraphQLHandler.d.ts +0 -6
  342. package/lib/core/handlers/GraphQLHandler.js +0 -232
  343. package/lib/core/handlers/GraphQLHandler.js.map +0 -1
  344. package/lib/core/handlers/GraphQLHandler.mjs +0 -221
  345. package/lib/core/handlers/GraphQLHandler.mjs.map +0 -1
  346. package/lib/core/handlers/HttpHandler.d.mts +0 -75
  347. package/lib/core/handlers/HttpHandler.d.ts +0 -75
  348. package/lib/core/handlers/HttpHandler.js +0 -129
  349. package/lib/core/handlers/HttpHandler.js.map +0 -1
  350. package/lib/core/handlers/HttpHandler.mjs +0 -113
  351. package/lib/core/handlers/HttpHandler.mjs.map +0 -1
  352. package/lib/core/handlers/RequestHandler.d.mts +0 -6
  353. package/lib/core/handlers/RequestHandler.d.ts +0 -6
  354. package/lib/core/handlers/RequestHandler.js +0 -300
  355. package/lib/core/handlers/RequestHandler.js.map +0 -1
  356. package/lib/core/handlers/RequestHandler.mjs +0 -283
  357. package/lib/core/handlers/RequestHandler.mjs.map +0 -1
  358. package/lib/core/handlers/WebSocketHandler.d.mts +0 -49
  359. package/lib/core/handlers/WebSocketHandler.d.ts +0 -49
  360. package/lib/core/handlers/WebSocketHandler.js +0 -178
  361. package/lib/core/handlers/WebSocketHandler.js.map +0 -1
  362. package/lib/core/handlers/WebSocketHandler.mjs +0 -160
  363. package/lib/core/handlers/WebSocketHandler.mjs.map +0 -1
  364. package/lib/core/http.d.mts +0 -31
  365. package/lib/core/http.js +0 -41
  366. package/lib/core/http.js.map +0 -1
  367. package/lib/core/http.mjs +0 -25
  368. package/lib/core/http.mjs.map +0 -1
  369. package/lib/core/index.d.mts +0 -27
  370. package/lib/core/index.js.map +0 -1
  371. package/lib/core/index.mjs +0 -52
  372. package/lib/core/index.mjs.map +0 -1
  373. package/lib/core/isCommonAssetRequest.d.mts +0 -20
  374. package/lib/core/isCommonAssetRequest.d.ts +0 -20
  375. package/lib/core/isCommonAssetRequest.js +0 -42
  376. package/lib/core/isCommonAssetRequest.js.map +0 -1
  377. package/lib/core/isCommonAssetRequest.mjs +0 -22
  378. package/lib/core/isCommonAssetRequest.mjs.map +0 -1
  379. package/lib/core/on-unhandled-frame-0KmwUmeV.d.ts +0 -56
  380. package/lib/core/on-unhandled-frame-gkokW4Rr.d.mts +0 -56
  381. package/lib/core/passthrough.d.mts +0 -24
  382. package/lib/core/passthrough.d.ts +0 -24
  383. package/lib/core/passthrough.js +0 -33
  384. package/lib/core/passthrough.js.map +0 -1
  385. package/lib/core/passthrough.mjs +0 -13
  386. package/lib/core/passthrough.mjs.map +0 -1
  387. package/lib/core/sharedOptions.d.mts +0 -68
  388. package/lib/core/sharedOptions.d.ts +0 -68
  389. package/lib/core/sharedOptions.js +0 -17
  390. package/lib/core/sharedOptions.js.map +0 -1
  391. package/lib/core/sharedOptions.mjs +0 -1
  392. package/lib/core/sharedOptions.mjs.map +0 -1
  393. package/lib/core/sse.d.mts +0 -102
  394. package/lib/core/sse.d.ts +0 -102
  395. package/lib/core/sse.js +0 -672
  396. package/lib/core/sse.js.map +0 -1
  397. package/lib/core/sse.mjs +0 -654
  398. package/lib/core/sse.mjs.map +0 -1
  399. package/lib/core/typeUtils.d.mts +0 -12
  400. package/lib/core/typeUtils.d.ts +0 -12
  401. package/lib/core/typeUtils.js +0 -17
  402. package/lib/core/typeUtils.js.map +0 -1
  403. package/lib/core/typeUtils.mjs +0 -1
  404. package/lib/core/typeUtils.mjs.map +0 -1
  405. package/lib/core/utils/HttpResponse/decorators.d.mts +0 -17
  406. package/lib/core/utils/HttpResponse/decorators.d.ts +0 -17
  407. package/lib/core/utils/HttpResponse/decorators.js +0 -71
  408. package/lib/core/utils/HttpResponse/decorators.js.map +0 -1
  409. package/lib/core/utils/HttpResponse/decorators.mjs +0 -41
  410. package/lib/core/utils/HttpResponse/decorators.mjs.map +0 -1
  411. package/lib/core/utils/cookieStore.d.mts +0 -13
  412. package/lib/core/utils/cookieStore.d.ts +0 -13
  413. package/lib/core/utils/cookieStore.js +0 -90
  414. package/lib/core/utils/cookieStore.js.map +0 -1
  415. package/lib/core/utils/cookieStore.mjs +0 -74
  416. package/lib/core/utils/cookieStore.mjs.map +0 -1
  417. package/lib/core/utils/executeHandlers.d.mts +0 -6
  418. package/lib/core/utils/executeHandlers.d.ts +0 -6
  419. package/lib/core/utils/executeHandlers.js +0 -51
  420. package/lib/core/utils/executeHandlers.js.map +0 -1
  421. package/lib/core/utils/executeHandlers.mjs +0 -31
  422. package/lib/core/utils/executeHandlers.mjs.map +0 -1
  423. package/lib/core/utils/handleRequest.d.mts +0 -30
  424. package/lib/core/utils/handleRequest.d.ts +0 -30
  425. package/lib/core/utils/handleRequest.js +0 -76
  426. package/lib/core/utils/handleRequest.js.map +0 -1
  427. package/lib/core/utils/handleRequest.mjs +0 -58
  428. package/lib/core/utils/handleRequest.mjs.map +0 -1
  429. package/lib/core/utils/internal/Disposable.d.mts +0 -7
  430. package/lib/core/utils/internal/Disposable.d.ts +0 -7
  431. package/lib/core/utils/internal/Disposable.js +0 -51
  432. package/lib/core/utils/internal/Disposable.js.map +0 -1
  433. package/lib/core/utils/internal/Disposable.mjs +0 -31
  434. package/lib/core/utils/internal/Disposable.mjs.map +0 -1
  435. package/lib/core/utils/internal/attachSiblingHandlers.d.mts +0 -15
  436. package/lib/core/utils/internal/attachSiblingHandlers.d.ts +0 -15
  437. package/lib/core/utils/internal/attachSiblingHandlers.js +0 -44
  438. package/lib/core/utils/internal/attachSiblingHandlers.js.map +0 -1
  439. package/lib/core/utils/internal/attachSiblingHandlers.mjs +0 -24
  440. package/lib/core/utils/internal/attachSiblingHandlers.mjs.map +0 -1
  441. package/lib/core/utils/internal/checkGlobals.d.mts +0 -3
  442. package/lib/core/utils/internal/checkGlobals.d.ts +0 -3
  443. package/lib/core/utils/internal/checkGlobals.js +0 -34
  444. package/lib/core/utils/internal/checkGlobals.js.map +0 -1
  445. package/lib/core/utils/internal/checkGlobals.mjs +0 -14
  446. package/lib/core/utils/internal/checkGlobals.mjs.map +0 -1
  447. package/lib/core/utils/internal/devUtils.d.mts +0 -28
  448. package/lib/core/utils/internal/devUtils.d.ts +0 -28
  449. package/lib/core/utils/internal/devUtils.js +0 -48
  450. package/lib/core/utils/internal/devUtils.js.map +0 -1
  451. package/lib/core/utils/internal/devUtils.mjs +0 -28
  452. package/lib/core/utils/internal/devUtils.mjs.map +0 -1
  453. package/lib/core/utils/internal/getCallFrame.d.mts +0 -6
  454. package/lib/core/utils/internal/getCallFrame.d.ts +0 -6
  455. package/lib/core/utils/internal/getCallFrame.js +0 -41
  456. package/lib/core/utils/internal/getCallFrame.js.map +0 -1
  457. package/lib/core/utils/internal/getCallFrame.mjs +0 -21
  458. package/lib/core/utils/internal/getCallFrame.mjs.map +0 -1
  459. package/lib/core/utils/internal/hasRefCounted.d.mts +0 -3
  460. package/lib/core/utils/internal/hasRefCounted.d.ts +0 -3
  461. package/lib/core/utils/internal/hasRefCounted.js +0 -34
  462. package/lib/core/utils/internal/hasRefCounted.js.map +0 -1
  463. package/lib/core/utils/internal/hasRefCounted.mjs +0 -14
  464. package/lib/core/utils/internal/hasRefCounted.mjs.map +0 -1
  465. package/lib/core/utils/internal/isHandlerKind.d.mts +0 -19
  466. package/lib/core/utils/internal/isHandlerKind.d.ts +0 -19
  467. package/lib/core/utils/internal/isHandlerKind.js +0 -30
  468. package/lib/core/utils/internal/isHandlerKind.js.map +0 -1
  469. package/lib/core/utils/internal/isHandlerKind.mjs +0 -10
  470. package/lib/core/utils/internal/isHandlerKind.mjs.map +0 -1
  471. package/lib/core/utils/internal/isIterable.d.mts +0 -20
  472. package/lib/core/utils/internal/isIterable.d.ts +0 -20
  473. package/lib/core/utils/internal/isIterable.js +0 -30
  474. package/lib/core/utils/internal/isIterable.js.map +0 -1
  475. package/lib/core/utils/internal/isIterable.mjs +0 -10
  476. package/lib/core/utils/internal/isIterable.mjs.map +0 -1
  477. package/lib/core/utils/internal/isObject.d.mts +0 -6
  478. package/lib/core/utils/internal/isObject.d.ts +0 -6
  479. package/lib/core/utils/internal/isObject.js +0 -27
  480. package/lib/core/utils/internal/isObject.js.map +0 -1
  481. package/lib/core/utils/internal/isObject.mjs +0 -7
  482. package/lib/core/utils/internal/isObject.mjs.map +0 -1
  483. package/lib/core/utils/internal/isStringEqual.d.mts +0 -6
  484. package/lib/core/utils/internal/isStringEqual.d.ts +0 -6
  485. package/lib/core/utils/internal/isStringEqual.js +0 -27
  486. package/lib/core/utils/internal/isStringEqual.js.map +0 -1
  487. package/lib/core/utils/internal/isStringEqual.mjs +0 -7
  488. package/lib/core/utils/internal/isStringEqual.mjs.map +0 -1
  489. package/lib/core/utils/internal/jsonParse.d.mts +0 -7
  490. package/lib/core/utils/internal/jsonParse.d.ts +0 -7
  491. package/lib/core/utils/internal/jsonParse.js +0 -31
  492. package/lib/core/utils/internal/jsonParse.js.map +0 -1
  493. package/lib/core/utils/internal/jsonParse.mjs +0 -11
  494. package/lib/core/utils/internal/jsonParse.mjs.map +0 -1
  495. package/lib/core/utils/internal/mergeRight.d.mts +0 -7
  496. package/lib/core/utils/internal/mergeRight.d.ts +0 -7
  497. package/lib/core/utils/internal/mergeRight.js +0 -43
  498. package/lib/core/utils/internal/mergeRight.js.map +0 -1
  499. package/lib/core/utils/internal/mergeRight.mjs +0 -23
  500. package/lib/core/utils/internal/mergeRight.mjs.map +0 -1
  501. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +0 -6
  502. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +0 -6
  503. package/lib/core/utils/internal/parseGraphQLRequest.js +0 -146
  504. package/lib/core/utils/internal/parseGraphQLRequest.js.map +0 -1
  505. package/lib/core/utils/internal/parseGraphQLRequest.mjs +0 -129
  506. package/lib/core/utils/internal/parseGraphQLRequest.mjs.map +0 -1
  507. package/lib/core/utils/internal/parseMultipartData.d.mts +0 -14
  508. package/lib/core/utils/internal/parseMultipartData.d.ts +0 -14
  509. package/lib/core/utils/internal/parseMultipartData.js +0 -84
  510. package/lib/core/utils/internal/parseMultipartData.js.map +0 -1
  511. package/lib/core/utils/internal/parseMultipartData.mjs +0 -64
  512. package/lib/core/utils/internal/parseMultipartData.mjs.map +0 -1
  513. package/lib/core/utils/internal/pipeEvents.d.mts +0 -8
  514. package/lib/core/utils/internal/pipeEvents.d.ts +0 -8
  515. package/lib/core/utils/internal/pipeEvents.js +0 -37
  516. package/lib/core/utils/internal/pipeEvents.js.map +0 -1
  517. package/lib/core/utils/internal/pipeEvents.mjs +0 -17
  518. package/lib/core/utils/internal/pipeEvents.mjs.map +0 -1
  519. package/lib/core/utils/internal/toReadonlyArray.d.mts +0 -6
  520. package/lib/core/utils/internal/toReadonlyArray.d.ts +0 -6
  521. package/lib/core/utils/internal/toReadonlyArray.js +0 -29
  522. package/lib/core/utils/internal/toReadonlyArray.js.map +0 -1
  523. package/lib/core/utils/internal/toReadonlyArray.mjs +0 -9
  524. package/lib/core/utils/internal/toReadonlyArray.mjs.map +0 -1
  525. package/lib/core/utils/internal/tryCatch.d.mts +0 -3
  526. package/lib/core/utils/internal/tryCatch.d.ts +0 -3
  527. package/lib/core/utils/internal/tryCatch.js +0 -32
  528. package/lib/core/utils/internal/tryCatch.js.map +0 -1
  529. package/lib/core/utils/internal/tryCatch.mjs +0 -12
  530. package/lib/core/utils/internal/tryCatch.mjs.map +0 -1
  531. package/lib/core/utils/logging/getStatusCodeColor.d.mts +0 -11
  532. package/lib/core/utils/logging/getStatusCodeColor.d.ts +0 -11
  533. package/lib/core/utils/logging/getStatusCodeColor.js +0 -40
  534. package/lib/core/utils/logging/getStatusCodeColor.js.map +0 -1
  535. package/lib/core/utils/logging/getStatusCodeColor.mjs +0 -20
  536. package/lib/core/utils/logging/getStatusCodeColor.mjs.map +0 -1
  537. package/lib/core/utils/logging/getTimestamp.d.mts +0 -9
  538. package/lib/core/utils/logging/getTimestamp.d.ts +0 -9
  539. package/lib/core/utils/logging/getTimestamp.js +0 -32
  540. package/lib/core/utils/logging/getTimestamp.js.map +0 -1
  541. package/lib/core/utils/logging/getTimestamp.mjs +0 -12
  542. package/lib/core/utils/logging/getTimestamp.mjs.map +0 -1
  543. package/lib/core/utils/logging/serializeRequest.d.mts +0 -12
  544. package/lib/core/utils/logging/serializeRequest.d.ts +0 -12
  545. package/lib/core/utils/logging/serializeRequest.js +0 -34
  546. package/lib/core/utils/logging/serializeRequest.js.map +0 -1
  547. package/lib/core/utils/logging/serializeRequest.mjs +0 -14
  548. package/lib/core/utils/logging/serializeRequest.mjs.map +0 -1
  549. package/lib/core/utils/logging/serializeResponse.d.mts +0 -9
  550. package/lib/core/utils/logging/serializeResponse.d.ts +0 -9
  551. package/lib/core/utils/logging/serializeResponse.js +0 -48
  552. package/lib/core/utils/logging/serializeResponse.js.map +0 -1
  553. package/lib/core/utils/logging/serializeResponse.mjs +0 -18
  554. package/lib/core/utils/logging/serializeResponse.mjs.map +0 -1
  555. package/lib/core/utils/matching/matchRequestUrl.d.mts +0 -20
  556. package/lib/core/utils/matching/matchRequestUrl.d.ts +0 -20
  557. package/lib/core/utils/matching/matchRequestUrl.js +0 -55
  558. package/lib/core/utils/matching/matchRequestUrl.js.map +0 -1
  559. package/lib/core/utils/matching/matchRequestUrl.mjs +0 -35
  560. package/lib/core/utils/matching/matchRequestUrl.mjs.map +0 -1
  561. package/lib/core/utils/matching/normalizePath.d.mts +0 -13
  562. package/lib/core/utils/matching/normalizePath.d.ts +0 -13
  563. package/lib/core/utils/matching/normalizePath.js +0 -33
  564. package/lib/core/utils/matching/normalizePath.js.map +0 -1
  565. package/lib/core/utils/matching/normalizePath.mjs +0 -13
  566. package/lib/core/utils/matching/normalizePath.mjs.map +0 -1
  567. package/lib/core/utils/request/getAllAcceptedMimeTypes.d.mts +0 -14
  568. package/lib/core/utils/request/getAllAcceptedMimeTypes.d.ts +0 -14
  569. package/lib/core/utils/request/getAllAcceptedMimeTypes.js +0 -61
  570. package/lib/core/utils/request/getAllAcceptedMimeTypes.js.map +0 -1
  571. package/lib/core/utils/request/getAllAcceptedMimeTypes.mjs +0 -41
  572. package/lib/core/utils/request/getAllAcceptedMimeTypes.mjs.map +0 -1
  573. package/lib/core/utils/request/getRequestCookies.d.mts +0 -3
  574. package/lib/core/utils/request/getRequestCookies.d.ts +0 -3
  575. package/lib/core/utils/request/getRequestCookies.js +0 -79
  576. package/lib/core/utils/request/getRequestCookies.js.map +0 -1
  577. package/lib/core/utils/request/getRequestCookies.mjs +0 -62
  578. package/lib/core/utils/request/getRequestCookies.mjs.map +0 -1
  579. package/lib/core/utils/request/onUnhandledRequest.d.mts +0 -9
  580. package/lib/core/utils/request/onUnhandledRequest.d.ts +0 -9
  581. package/lib/core/utils/request/onUnhandledRequest.js +0 -76
  582. package/lib/core/utils/request/onUnhandledRequest.js.map +0 -1
  583. package/lib/core/utils/request/onUnhandledRequest.mjs +0 -56
  584. package/lib/core/utils/request/onUnhandledRequest.mjs.map +0 -1
  585. package/lib/core/utils/request/storeResponseCookies.d.mts +0 -3
  586. package/lib/core/utils/request/storeResponseCookies.d.ts +0 -3
  587. package/lib/core/utils/request/storeResponseCookies.js +0 -32
  588. package/lib/core/utils/request/storeResponseCookies.js.map +0 -1
  589. package/lib/core/utils/request/storeResponseCookies.mjs +0 -12
  590. package/lib/core/utils/request/storeResponseCookies.mjs.map +0 -1
  591. package/lib/core/utils/request/toPublicUrl.d.mts +0 -7
  592. package/lib/core/utils/request/toPublicUrl.d.ts +0 -7
  593. package/lib/core/utils/request/toPublicUrl.js +0 -31
  594. package/lib/core/utils/request/toPublicUrl.js.map +0 -1
  595. package/lib/core/utils/request/toPublicUrl.mjs +0 -11
  596. package/lib/core/utils/request/toPublicUrl.mjs.map +0 -1
  597. package/lib/core/utils/toResponseInit.d.mts +0 -3
  598. package/lib/core/utils/toResponseInit.d.ts +0 -3
  599. package/lib/core/utils/toResponseInit.js +0 -31
  600. package/lib/core/utils/toResponseInit.js.map +0 -1
  601. package/lib/core/utils/toResponseInit.mjs +0 -11
  602. package/lib/core/utils/toResponseInit.mjs.map +0 -1
  603. package/lib/core/utils/url/cleanUrl.d.mts +0 -7
  604. package/lib/core/utils/url/cleanUrl.d.ts +0 -7
  605. package/lib/core/utils/url/cleanUrl.js +0 -31
  606. package/lib/core/utils/url/cleanUrl.js.map +0 -1
  607. package/lib/core/utils/url/cleanUrl.mjs +0 -11
  608. package/lib/core/utils/url/cleanUrl.mjs.map +0 -1
  609. package/lib/core/utils/url/getAbsoluteUrl.d.mts +0 -6
  610. package/lib/core/utils/url/getAbsoluteUrl.d.ts +0 -6
  611. package/lib/core/utils/url/getAbsoluteUrl.js +0 -38
  612. package/lib/core/utils/url/getAbsoluteUrl.js.map +0 -1
  613. package/lib/core/utils/url/getAbsoluteUrl.mjs +0 -18
  614. package/lib/core/utils/url/getAbsoluteUrl.mjs.map +0 -1
  615. package/lib/core/utils/url/isAbsoluteUrl.d.mts +0 -6
  616. package/lib/core/utils/url/isAbsoluteUrl.d.ts +0 -6
  617. package/lib/core/utils/url/isAbsoluteUrl.js +0 -27
  618. package/lib/core/utils/url/isAbsoluteUrl.js.map +0 -1
  619. package/lib/core/utils/url/isAbsoluteUrl.mjs +0 -7
  620. package/lib/core/utils/url/isAbsoluteUrl.mjs.map +0 -1
  621. package/lib/core/ws/WebSocketClientManager.d.mts +0 -65
  622. package/lib/core/ws/WebSocketClientManager.d.ts +0 -65
  623. package/lib/core/ws/WebSocketClientManager.js +0 -163
  624. package/lib/core/ws/WebSocketClientManager.js.map +0 -1
  625. package/lib/core/ws/WebSocketClientManager.mjs +0 -143
  626. package/lib/core/ws/WebSocketClientManager.mjs.map +0 -1
  627. package/lib/core/ws/WebSocketClientStore.d.mts +0 -13
  628. package/lib/core/ws/WebSocketClientStore.d.ts +0 -13
  629. package/lib/core/ws/WebSocketClientStore.js +0 -26
  630. package/lib/core/ws/WebSocketClientStore.js.map +0 -1
  631. package/lib/core/ws/WebSocketClientStore.mjs +0 -6
  632. package/lib/core/ws/WebSocketClientStore.mjs.map +0 -1
  633. package/lib/core/ws/WebSocketIndexedDBClientStore.d.mts +0 -14
  634. package/lib/core/ws/WebSocketIndexedDBClientStore.d.ts +0 -14
  635. package/lib/core/ws/WebSocketIndexedDBClientStore.js +0 -131
  636. package/lib/core/ws/WebSocketIndexedDBClientStore.js.map +0 -1
  637. package/lib/core/ws/WebSocketIndexedDBClientStore.mjs +0 -111
  638. package/lib/core/ws/WebSocketIndexedDBClientStore.mjs.map +0 -1
  639. package/lib/core/ws/WebSocketMemoryClientStore.d.mts +0 -12
  640. package/lib/core/ws/WebSocketMemoryClientStore.d.ts +0 -12
  641. package/lib/core/ws/WebSocketMemoryClientStore.js +0 -42
  642. package/lib/core/ws/WebSocketMemoryClientStore.js.map +0 -1
  643. package/lib/core/ws/WebSocketMemoryClientStore.mjs +0 -22
  644. package/lib/core/ws/WebSocketMemoryClientStore.mjs.map +0 -1
  645. package/lib/core/ws/handleWebSocketEvent.d.mts +0 -20
  646. package/lib/core/ws/handleWebSocketEvent.d.ts +0 -20
  647. package/lib/core/ws/handleWebSocketEvent.js +0 -61
  648. package/lib/core/ws/handleWebSocketEvent.js.map +0 -1
  649. package/lib/core/ws/handleWebSocketEvent.mjs +0 -43
  650. package/lib/core/ws/handleWebSocketEvent.mjs.map +0 -1
  651. package/lib/core/ws/utils/attachWebSocketLogger.d.mts +0 -18
  652. package/lib/core/ws/utils/attachWebSocketLogger.d.ts +0 -18
  653. package/lib/core/ws/utils/attachWebSocketLogger.js +0 -228
  654. package/lib/core/ws/utils/attachWebSocketLogger.js.map +0 -1
  655. package/lib/core/ws/utils/attachWebSocketLogger.mjs +0 -208
  656. package/lib/core/ws/utils/attachWebSocketLogger.mjs.map +0 -1
  657. package/lib/core/ws/utils/getMessageLength.d.mts +0 -11
  658. package/lib/core/ws/utils/getMessageLength.d.ts +0 -11
  659. package/lib/core/ws/utils/getMessageLength.js +0 -34
  660. package/lib/core/ws/utils/getMessageLength.js.map +0 -1
  661. package/lib/core/ws/utils/getMessageLength.mjs +0 -14
  662. package/lib/core/ws/utils/getMessageLength.mjs.map +0 -1
  663. package/lib/core/ws/utils/getPublicData.d.mts +0 -5
  664. package/lib/core/ws/utils/getPublicData.d.ts +0 -5
  665. package/lib/core/ws/utils/getPublicData.js +0 -37
  666. package/lib/core/ws/utils/getPublicData.js.map +0 -1
  667. package/lib/core/ws/utils/getPublicData.mjs +0 -17
  668. package/lib/core/ws/utils/getPublicData.mjs.map +0 -1
  669. package/lib/core/ws/utils/truncateMessage.d.mts +0 -3
  670. package/lib/core/ws/utils/truncateMessage.d.ts +0 -3
  671. package/lib/core/ws/utils/truncateMessage.js +0 -31
  672. package/lib/core/ws/utils/truncateMessage.js.map +0 -1
  673. package/lib/core/ws/utils/truncateMessage.mjs +0 -11
  674. package/lib/core/ws/utils/truncateMessage.mjs.map +0 -1
  675. package/lib/core/ws/webSocketInterceptor.d.mts +0 -5
  676. package/lib/core/ws/webSocketInterceptor.d.ts +0 -5
  677. package/lib/core/ws/webSocketInterceptor.js +0 -26
  678. package/lib/core/ws/webSocketInterceptor.js.map +0 -1
  679. package/lib/core/ws/webSocketInterceptor.mjs +0 -6
  680. package/lib/core/ws/webSocketInterceptor.mjs.map +0 -1
  681. package/lib/core/ws.d.mts +0 -88
  682. package/lib/core/ws.d.ts +0 -88
  683. package/lib/core/ws.js +0 -94
  684. package/lib/core/ws.js.map +0 -1
  685. package/lib/core/ws.mjs +0 -80
  686. package/lib/core/ws.mjs.map +0 -1
  687. package/lib/native/index.d.mts +0 -66
  688. package/lib/native/index.d.ts +0 -66
  689. package/lib/native/index.js +0 -88
  690. package/lib/native/index.js.map +0 -1
  691. package/lib/native/index.mjs +0 -67
  692. package/lib/native/index.mjs.map +0 -1
  693. package/lib/node/index.d.mts +0 -113
  694. package/lib/node/index.mjs +0 -185
  695. package/lib/node/index.mjs.map +0 -1
  696. package/lib/shims/cookie.d.mts +0 -7
  697. package/lib/shims/cookie.d.ts +0 -7
  698. package/lib/shims/cookie.js +0 -294
  699. package/lib/shims/cookie.mjs +0 -286
  700. package/lib/shims/statuses.d.mts +0 -6
  701. package/lib/shims/statuses.d.ts +0 -6
  702. package/lib/shims/statuses.js +0 -195
  703. package/lib/shims/statuses.mjs +0 -187
  704. package/native/package.json +0 -30
  705. package/node/package.json +0 -33
  706. package/src/browser/utils/pruneGetRequestBody.test.ts +0 -51
  707. package/src/browser/utils/pruneGetRequestBody.ts +0 -21
  708. package/src/core/experimental/compat.ts +0 -50
  709. package/src/core/experimental/setup-api.ts +0 -55
  710. package/src/core/graphql.test.ts +0 -11
  711. package/src/core/graphql.ts +0 -136
  712. package/src/core/passthrough.test.ts +0 -11
  713. package/src/core/passthrough.ts +0 -25
  714. package/src/core/sharedOptions.ts +0 -71
  715. package/src/core/typeUtils.ts +0 -26
  716. package/src/core/utils/handleRequest.test.ts +0 -574
  717. package/src/core/utils/handleRequest.ts +0 -117
  718. package/src/core/utils/internal/checkGlobals.ts +0 -17
  719. package/src/core/utils/internal/isHandlerKind.test.ts +0 -62
  720. package/src/core/utils/internal/isHandlerKind.ts +0 -17
  721. package/src/core/utils/internal/isIterable.ts +0 -32
  722. package/src/core/utils/internal/mergeRight.test.ts +0 -43
  723. package/src/core/utils/internal/mergeRight.ts +0 -30
  724. package/src/core/utils/internal/pipeEvents.test.ts +0 -14
  725. package/src/core/utils/internal/pipeEvents.ts +0 -26
  726. package/src/core/utils/internal/tryCatch.test.ts +0 -29
  727. package/src/core/utils/internal/tryCatch.ts +0 -11
  728. package/src/core/utils/matching/matchRequestUrl.test.ts +0 -267
  729. package/src/core/utils/matching/matchRequestUrl.ts +0 -77
  730. package/src/core/utils/request/getRequestCookies.ts +0 -88
  731. package/src/core/utils/request/onUnhandledRequest.node.test.ts +0 -62
  732. package/src/core/utils/request/onUnhandledRequest.test.ts +0 -226
  733. package/src/core/utils/request/onUnhandledRequest.ts +0 -81
  734. package/src/core/utils/request/storeResponseCookies.ts +0 -15
  735. package/src/core/utils/url/cleanUrl.test.ts +0 -22
  736. package/src/core/utils/url/cleanUrl.ts +0 -16
  737. package/src/core/utils/url/isAbsoluteUrl.test.ts +0 -32
  738. package/src/core/ws/handleWebSocketEvent.ts +0 -68
  739. package/src/core/ws/utils/getPublicData.ts +0 -18
  740. package/src/core/ws/webSocketInterceptor.ts +0 -3
  741. package/src/native/index.ts +0 -44
  742. package/src/package.json +0 -3
  743. package/src/shims/cookie.ts +0 -7
  744. package/src/shims/statuses.ts +0 -6
  745. /package/src/browser/utils/{getAbsoluteWorkerUrl.ts → get-absolute-worker-url.ts} +0 -0
  746. /package/src/core/utils/internal/{devUtils.ts → dev-utils.ts} +0 -0
  747. /package/src/core/utils/internal/{isObject.ts → is-object.ts} +0 -0
  748. /package/src/core/utils/internal/{isStringEqual.ts → is-string-equal.ts} +0 -0
  749. /package/src/core/utils/internal/{jsonParse.ts → json-parse.ts} +0 -0
  750. /package/src/core/utils/internal/{toReadonlyArray.ts → to-readonly-array.ts} +0 -0
  751. /package/src/core/utils/logging/{getStatusCodeColor.ts → get-status-code-color.ts} +0 -0
  752. /package/src/core/utils/logging/{getTimestamp.ts → get-timestamp.ts} +0 -0
  753. /package/src/core/utils/logging/{serializeRequest.ts → serialize-request.ts} +0 -0
  754. /package/src/core/utils/request/{getAllAcceptedMimeTypes.ts → get-all-accepted-mime-types.ts} +0 -0
  755. /package/src/core/utils/request/{toPublicUrl.ts → to-public-url.ts} +0 -0
  756. /package/src/core/utils/{toResponseInit.ts → to-response-init.ts} +0 -0
  757. /package/src/core/utils/url/{isAbsoluteUrl.ts → is-absolute-url.ts} +0 -0
  758. /package/src/{core → http}/http.test.ts +0 -0
  759. /package/src/{core/ws/utils/truncateMessage.ts → ws/utils/truncate-message.ts} +0 -0
@@ -0,0 +1,1487 @@
1
+ import { invariant } from 'outvariant'
2
+ import { Emitter, TypedEvent } from 'rettime'
3
+ import { parse, OperationTypeNode, type GraphQLError } from 'graphql'
4
+ import { resolveWebSocketUrl } from '@mswjs/interceptors'
5
+ import type {
6
+ WebSocketClientHandle,
7
+ WebSocketConnectionEventData,
8
+ WebSocketData,
9
+ WebSocketServerHandle,
10
+ } from '@mswjs/interceptors/WebSocket'
11
+ import { http } from '#http/http'
12
+ import { webSocketUpgrade } from '#ws/websocket-upgrade'
13
+ import {
14
+ WebSocketHandler,
15
+ kConnect,
16
+ type WebSocketHandlerConnection,
17
+ type WebSocketResolutionContext,
18
+ } from '#ws/websocket-handler'
19
+ import { GraphQLSubscriptionEvent } from './graphql-subscription-event'
20
+ import {
21
+ matchRequestUrl,
22
+ type Path,
23
+ type PathParams,
24
+ } from '#core/utils/matching/match-request-url'
25
+ import type { ResponseResolverFinalizeFunction } from '#core/handlers/request-handler'
26
+ import type { MaybePromise } from '#core/type-utils'
27
+ import { attachSiblingHandlers } from '#core/utils/internal/attach-sibling-handlers'
28
+ import { jsonParse } from '#core/utils/internal/json-parse'
29
+ import { devUtils } from '#core/utils/internal/dev-utils'
30
+ import { getTimestamp } from '#core/utils/logging/get-timestamp'
31
+ import { toPublicUrl } from '#core/utils/request/to-public-url'
32
+ import { colors } from '#core/utils/logging/colors'
33
+ import {
34
+ GraphQLHandler,
35
+ isDocumentNode,
36
+ type DocumentTypeDecoration,
37
+ type GraphQLHandlerInfo,
38
+ type GraphQLHandlerNameSelector,
39
+ type GraphQLQuery,
40
+ type GraphQLVariables,
41
+ } from './graphql-handler'
42
+ import {
43
+ parseDocumentNode,
44
+ type ParsedGraphQLQuery,
45
+ } from './parse-graphql-request'
46
+
47
+ /**
48
+ * Messages of the `graphql-transport-ws` protocol.
49
+ * @see https://github.com/graphql/graphql-over-http/blob/main/rfcs/GraphQLOverWebSocket.md
50
+ */
51
+ interface GraphQLWebSocketInitMessage {
52
+ type: 'connection_init'
53
+ payload?: Record<string, unknown>
54
+ }
55
+
56
+ interface GraphQLWebSocketSubscribePayload<
57
+ Variables extends GraphQLVariables = GraphQLVariables,
58
+ > {
59
+ operationName?: string | null
60
+ query: string
61
+ variables?: Variables
62
+ extensions?: Record<string, unknown>
63
+ }
64
+
65
+ export interface GraphQLWebSocketSubscribeMessage<
66
+ Variables extends GraphQLVariables = GraphQLVariables,
67
+ > {
68
+ type: 'subscribe'
69
+ id: string
70
+ payload: GraphQLWebSocketSubscribePayload<Variables>
71
+ }
72
+
73
+ interface GraphQLWebSocketCompleteMessage {
74
+ type: 'complete'
75
+ id: string
76
+ }
77
+
78
+ interface GraphQLWebSocketPingMessage {
79
+ type: 'ping'
80
+ payload?: Record<string, unknown>
81
+ }
82
+
83
+ interface GraphQLWebSocketPongMessage {
84
+ type: 'pong'
85
+ payload?: Record<string, unknown>
86
+ }
87
+
88
+ type GraphQLWebSocketClientMessage =
89
+ | GraphQLWebSocketInitMessage
90
+ | GraphQLWebSocketSubscribeMessage
91
+ | GraphQLWebSocketCompleteMessage
92
+ | GraphQLWebSocketPingMessage
93
+ | GraphQLWebSocketPongMessage
94
+
95
+ interface GraphQLWebSocketAcknowledgeMessage {
96
+ type: 'connection_ack'
97
+ payload?: Record<string, unknown>
98
+ }
99
+
100
+ interface GraphQLWebSocketNextMessage {
101
+ type: 'next'
102
+ id: string
103
+ payload: GraphQLSubscriptionPayload
104
+ }
105
+
106
+ interface GraphQLWebSocketErrorMessage {
107
+ type: 'error'
108
+ id: string
109
+ payload: ReadonlyArray<Partial<GraphQLError>>
110
+ }
111
+
112
+ type GraphQLWebSocketServerMessage =
113
+ | GraphQLWebSocketAcknowledgeMessage
114
+ | GraphQLWebSocketNextMessage
115
+ | GraphQLWebSocketErrorMessage
116
+ | GraphQLWebSocketCompleteMessage
117
+ | GraphQLWebSocketPingMessage
118
+ | GraphQLWebSocketPongMessage
119
+
120
+ /**
121
+ * A GraphQL execution result published to a subscription.
122
+ */
123
+ export interface GraphQLSubscriptionPayload<
124
+ Query extends GraphQLQuery = GraphQLQuery,
125
+ > {
126
+ data?: Query | null
127
+ errors?: ReadonlyArray<Partial<GraphQLError>> | null
128
+ extensions?: Record<string, unknown>
129
+ }
130
+
131
+ function createInitMessage(payload?: Record<string, unknown>): string {
132
+ return JSON.stringify({
133
+ type: 'connection_init',
134
+ payload,
135
+ } satisfies GraphQLWebSocketInitMessage)
136
+ }
137
+
138
+ function createAcknowledgeMessage(): string {
139
+ return JSON.stringify({
140
+ type: 'connection_ack',
141
+ } satisfies GraphQLWebSocketAcknowledgeMessage)
142
+ }
143
+
144
+ function createNextMessage(args: {
145
+ id: string
146
+ payload: GraphQLSubscriptionPayload
147
+ }): string {
148
+ return JSON.stringify({
149
+ id: args.id,
150
+ type: 'next',
151
+ payload: args.payload,
152
+ } satisfies GraphQLWebSocketNextMessage)
153
+ }
154
+
155
+ function createErrorMessage(args: {
156
+ id: string
157
+ payload: ReadonlyArray<Partial<GraphQLError>>
158
+ }): string {
159
+ return JSON.stringify({
160
+ id: args.id,
161
+ type: 'error',
162
+ payload: args.payload,
163
+ } satisfies GraphQLWebSocketErrorMessage)
164
+ }
165
+
166
+ function createCompleteMessage(args: { id: string }): string {
167
+ return JSON.stringify({
168
+ id: args.id,
169
+ type: 'complete',
170
+ } satisfies GraphQLWebSocketCompleteMessage)
171
+ }
172
+
173
+ function createPongMessage(): string {
174
+ return JSON.stringify({
175
+ type: 'pong',
176
+ } satisfies GraphQLWebSocketPongMessage)
177
+ }
178
+
179
+ /**
180
+ * Construct a request representing the WebSocket upgrade of the given
181
+ * connection. GraphQL subscriptions have no request of their own, so
182
+ * this describes the connection they are multiplexed over.
183
+ */
184
+ function createUpgradeRequest(url: URL): Request {
185
+ return new Request(url, {
186
+ headers: {
187
+ connection: 'upgrade',
188
+ upgrade: 'websocket',
189
+ },
190
+ })
191
+ }
192
+
193
+ function parseGraphQLWebSocketMessage<MessageType extends { type: string }>(
194
+ data: WebSocketData,
195
+ ): MessageType | undefined {
196
+ if (typeof data !== 'string') {
197
+ return undefined
198
+ }
199
+
200
+ const message = jsonParse<MessageType>(data)
201
+
202
+ if (!message || typeof message.type !== 'string') {
203
+ return undefined
204
+ }
205
+
206
+ return message
207
+ }
208
+
209
+ /**
210
+ * A subscriber provided by a `GraphQLSubscriptionHandler` for a particular
211
+ * WebSocket connection. Returns true if the handler matched the parsed
212
+ * subscribe operation and resolved it.
213
+ */
214
+ type GraphQLSubscriptionSubscriber = (args: {
215
+ node: ParsedGraphQLQuery
216
+ message: GraphQLWebSocketSubscribeMessage
217
+ }) => boolean
218
+
219
+ interface GraphQLSubscriptionSubscriberEntry {
220
+ transport: GraphQLSubscriptionTransportHandler
221
+ subscriber: GraphQLSubscriptionSubscriber
222
+ }
223
+
224
+ type GraphQLSubscriptionCleanup = () => MaybePromise<void>
225
+
226
+ interface GraphQLSubscriptionConnection {
227
+ client: WebSocketClientHandle
228
+ server: WebSocketServerHandle
229
+ subscribers: Map<WebSocketHandler, GraphQLSubscriptionSubscriberEntry>
230
+ /**
231
+ * The active subscriptions of this connection, mapped to the cleanups
232
+ * scheduled for them via the resolver's `finalize()`.
233
+ */
234
+ subscriptions: Map<string, Array<GraphQLSubscriptionCleanup>>
235
+ events?: WebSocketResolutionContext['events']
236
+ /**
237
+ * The payload of the client's `connection_init` message (i.e. the
238
+ * `connectionParams` of the GraphQL client). Kept so it can be
239
+ * replayed to the original server on passthrough.
240
+ */
241
+ connectionParams?: Record<string, unknown>
242
+ /**
243
+ * Resolves once the original server has acknowledged this connection.
244
+ * The upstream session is established once per connection, no matter
245
+ * how many subscriptions pass through it.
246
+ */
247
+ upstreamSession?: Promise<void>
248
+ }
249
+
250
+ /**
251
+ * Connect to the original server and initialize the `graphql-transport-ws`
252
+ * session for the given connection, at most once.
253
+ *
254
+ * @note The server connection is shared by every subscription of this
255
+ * client. Initializing it more than once makes a compliant GraphQL server
256
+ * close it ("Too many initialisation requests").
257
+ */
258
+ function ensureUpstreamSession(
259
+ connection: GraphQLSubscriptionConnection,
260
+ ): Promise<void> {
261
+ if (connection.upstreamSession) {
262
+ return connection.upstreamSession
263
+ }
264
+
265
+ const { server } = connection
266
+
267
+ connection.upstreamSession = new Promise<void>((resolve) => {
268
+ server.addEventListener('message', (event) => {
269
+ const message =
270
+ parseGraphQLWebSocketMessage<GraphQLWebSocketServerMessage>(event.data)
271
+
272
+ if (message?.type === 'connection_ack') {
273
+ // Prevent the original acknowledgement from being forwarded to
274
+ // the client: it has already received a mocked one on connect.
275
+ event.preventDefault()
276
+ resolve()
277
+ }
278
+ })
279
+
280
+ server.addEventListener(
281
+ 'open',
282
+ () => {
283
+ server.send(createInitMessage(connection.connectionParams))
284
+ },
285
+ { once: true },
286
+ )
287
+
288
+ server.connect()
289
+ })
290
+
291
+ return connection.upstreamSession
292
+ }
293
+
294
+ /**
295
+ * The `graphql-transport-ws` sessions of the intercepted WebSocket
296
+ * connections, keyed by the client id.
297
+ *
298
+ * @note This registry is module-level, and not per-transport, on purpose.
299
+ * Multiple `graphql.link()` calls to the same endpoint create multiple
300
+ * transports, and all of them must share a single session per connection.
301
+ * Otherwise, each transport binds its own protocol listeners to the same
302
+ * client, which makes it receive duplicate `connection_ack`/`pong` frames
303
+ * and resolves matching subscription handlers more than once.
304
+ */
305
+ const connections = new Map<string, GraphQLSubscriptionConnection>()
306
+
307
+ /**
308
+ * The WebSocket protocol implemented by the subscription transport.
309
+ * @see https://github.com/graphql/graphql-over-http/blob/main/rfcs/GraphQLOverWebSocket.md
310
+ */
311
+ const GRAPHQL_WEBSOCKET_SUBPROTOCOL = 'graphql-transport-ws'
312
+
313
+ function includesGraphQLProtocol(
314
+ protocols: string | Array<string> | null | undefined,
315
+ ): boolean {
316
+ if (protocols == null) {
317
+ return false
318
+ }
319
+
320
+ // Support both the WebSocket constructor argument (a protocol string
321
+ // or a list of protocol strings) and the `Sec-WebSocket-Protocol`
322
+ // request header (a comma-separated list).
323
+ const requestedProtocols =
324
+ typeof protocols === 'string' ? protocols.split(',') : protocols
325
+
326
+ return requestedProtocols.some((protocol) => {
327
+ return protocol.trim() === GRAPHQL_WEBSOCKET_SUBPROTOCOL
328
+ })
329
+ }
330
+
331
+ /**
332
+ * A WebSocket handler that only matches connections that requested the
333
+ * `graphql-transport-ws` protocol. Connections without it (e.g.
334
+ * arbitrary non-GraphQL WebSockets whose URL matched a permissive
335
+ * endpoint like a wildcard link) are left unhandled so they follow the
336
+ * regular unhandled connection flow (warnings, passthrough).
337
+ */
338
+ abstract class GraphQLWebSocketHandler extends WebSocketHandler {
339
+ public async run(
340
+ connection: WebSocketConnectionEventData,
341
+ resolutionContext?: WebSocketResolutionContext,
342
+ ): Promise<WebSocketHandlerConnection | null> {
343
+ if (!includesGraphQLProtocol(connection.info.protocols)) {
344
+ return null
345
+ }
346
+
347
+ return super.run(connection, resolutionContext)
348
+ }
349
+ }
350
+
351
+ /**
352
+ * A WebSocket handler implementing the `graphql-transport-ws` protocol
353
+ * session for a single GraphQL endpoint. One transport is shared across
354
+ * all subscription handlers created from the same `graphql.link()` call
355
+ * (attached to each of them as a sibling handler).
356
+ *
357
+ * The transport owns the protocol/session concerns: connection
358
+ * acknowledgement, keep-alive, the per-connection registry of active
359
+ * subscriptions, and dispatching parsed `subscribe` operations to the
360
+ * matching subscription handler.
361
+ */
362
+ export class GraphQLSubscriptionTransportHandler extends GraphQLWebSocketHandler {
363
+ /**
364
+ * Register the given handler as a subscriber to the GraphQL
365
+ * subscriptions on the given WebSocket connection. Subscribers are
366
+ * dispatched in registration order, which follows the handlers
367
+ * resolution order (runtime handlers take precedence).
368
+ */
369
+ public subscribe(
370
+ connection: WebSocketHandlerConnection,
371
+ handler: WebSocketHandler,
372
+ subscriber: GraphQLSubscriptionSubscriber,
373
+ ): void {
374
+ const transportConnection = this.#getOrCreateConnection(connection)
375
+ transportConnection.subscribers.set(handler, {
376
+ transport: this,
377
+ subscriber,
378
+ })
379
+ }
380
+
381
+ public getConnection(
382
+ clientId: string,
383
+ ): GraphQLSubscriptionConnection | undefined {
384
+ return connections.get(clientId)
385
+ }
386
+
387
+ public async run(
388
+ connection: WebSocketConnectionEventData,
389
+ resolutionContext?: WebSocketResolutionContext,
390
+ ): Promise<WebSocketHandlerConnection | null> {
391
+ const handlerConnection = await super.run(connection, resolutionContext)
392
+
393
+ // Capture the network frame events reference for this connection.
394
+ // The transport emits life-cycle events (e.g. "graphql:subscription")
395
+ // long after the run: whenever the client sends a "subscribe" message.
396
+ if (handlerConnection) {
397
+ const transportConnection = this.#getOrCreateConnection(handlerConnection)
398
+
399
+ // Never overwrite the events of a session shared with another
400
+ // transport: only the frame that resolved it provides them.
401
+ if (resolutionContext?.events) {
402
+ transportConnection.events = resolutionContext.events
403
+ }
404
+ }
405
+
406
+ return handlerConnection
407
+ }
408
+
409
+ /**
410
+ * End the given subscription without notifying the client. Used when
411
+ * the subscription has already been terminated over the wire (e.g. the
412
+ * original server completed it and that frame reached the client).
413
+ */
414
+ public endSubscription(args: {
415
+ clientId: string
416
+ subscriptionId: string
417
+ }): void {
418
+ const connection = connections.get(args.clientId)
419
+
420
+ if (connection) {
421
+ this.#endSubscription(connection, args.subscriptionId)
422
+ }
423
+ }
424
+
425
+ /**
426
+ * Schedule a cleanup to run once the given subscription ends.
427
+ *
428
+ * @note If the subscription has already ended by the time this is
429
+ * called, the cleanup runs immediately. The resolver can no longer
430
+ * affect that subscription, so there is nothing left to wait for.
431
+ */
432
+ public finalize(args: {
433
+ clientId: string
434
+ subscriptionId: string
435
+ cleanup: GraphQLSubscriptionCleanup
436
+ }): void {
437
+ const cleanups = connections
438
+ .get(args.clientId)
439
+ ?.subscriptions.get(args.subscriptionId)
440
+
441
+ if (cleanups) {
442
+ cleanups.push(args.cleanup)
443
+ return
444
+ }
445
+
446
+ this.#exhaustCleanups([args.cleanup])
447
+ }
448
+
449
+ async #endAllSubscriptions(
450
+ connection: GraphQLSubscriptionConnection,
451
+ ): Promise<void> {
452
+ const pendingCleanups: Array<Promise<void>> = []
453
+
454
+ for (const subscriptionId of connection.subscriptions.keys()) {
455
+ pendingCleanups.push(this.#endSubscription(connection, subscriptionId))
456
+ }
457
+
458
+ await Promise.all(pendingCleanups)
459
+ }
460
+
461
+ /**
462
+ * End the given subscription and run the cleanups scheduled for it.
463
+ *
464
+ * This is the single exit point for every way a subscription can end:
465
+ * completed by the mock, by the client, or by the original server;
466
+ * terminated with errors; dropped when the client disconnects; or
467
+ * detached from its resolver when the handlers are reset. Ending an
468
+ * already-ended subscription is a no-op, so the cleanups are
469
+ * guaranteed to run at most once.
470
+ */
471
+ #endSubscription(
472
+ connection: GraphQLSubscriptionConnection,
473
+ subscriptionId: string,
474
+ ): Promise<void> {
475
+ const cleanups = connection.subscriptions.get(subscriptionId)
476
+
477
+ if (!cleanups) {
478
+ return Promise.resolve()
479
+ }
480
+
481
+ connection.subscriptions.delete(subscriptionId)
482
+ return this.#exhaustCleanups(cleanups)
483
+ }
484
+
485
+ /**
486
+ * Run the given cleanups as LIFO, consistently with `finalize()` in
487
+ * the request handlers. Cleanups are detached from the subscription
488
+ * life-cycle: nothing awaits them, so this must never reject.
489
+ */
490
+ async #exhaustCleanups(
491
+ cleanups: Array<GraphQLSubscriptionCleanup>,
492
+ ): Promise<void> {
493
+ const errors: Array<Error> = []
494
+
495
+ for (let index = cleanups.length - 1; index >= 0; index--) {
496
+ try {
497
+ await cleanups[index]()
498
+ } catch (error) {
499
+ if (error instanceof Error) {
500
+ errors.push(error)
501
+ }
502
+ }
503
+ }
504
+
505
+ if (errors.length > 0) {
506
+ devUtils.error(
507
+ 'Failed to execute the cleanup for a GraphQL subscription to "%s". Please see the original error below.',
508
+ this.url.toString(),
509
+ new AggregateError(errors),
510
+ )
511
+ }
512
+ }
513
+
514
+ /**
515
+ * Send a `next` message with the given payload to the subscription.
516
+ */
517
+ public publish(args: {
518
+ clientId: string
519
+ subscriptionId: string
520
+ payload: GraphQLSubscriptionPayload
521
+ }): void {
522
+ const connection = this.#getConnectionForSubscription({
523
+ clientId: args.clientId,
524
+ subscriptionId: args.subscriptionId,
525
+ intent: 'publish to',
526
+ })
527
+
528
+ if (!connection) {
529
+ return
530
+ }
531
+
532
+ connection.client.send(
533
+ createNextMessage({
534
+ id: args.subscriptionId,
535
+ payload: args.payload,
536
+ }),
537
+ )
538
+ }
539
+
540
+ /**
541
+ * Send a terminal `error` message to the subscription and
542
+ * removes it from the registry of active subscriptions.
543
+ */
544
+ public error(args: {
545
+ clientId: string
546
+ subscriptionId: string
547
+ errors: ReadonlyArray<Partial<GraphQLError>>
548
+ }): void {
549
+ const connection = this.#getConnectionForSubscription({
550
+ clientId: args.clientId,
551
+ subscriptionId: args.subscriptionId,
552
+ intent: 'error',
553
+ })
554
+
555
+ if (!connection) {
556
+ return
557
+ }
558
+
559
+ connection.client.send(
560
+ createErrorMessage({
561
+ id: args.subscriptionId,
562
+ payload: args.errors,
563
+ }),
564
+ )
565
+ this.#endSubscription(connection, args.subscriptionId)
566
+ }
567
+
568
+ /**
569
+ * Send a `complete` message to the subscription and removes it
570
+ * from the registry of active subscriptions.
571
+ */
572
+ public complete(args: { clientId: string; subscriptionId: string }): void {
573
+ const connection = this.#getConnectionForSubscription({
574
+ clientId: args.clientId,
575
+ subscriptionId: args.subscriptionId,
576
+ intent: 'complete',
577
+ })
578
+
579
+ if (!connection) {
580
+ return
581
+ }
582
+
583
+ connection.client.send(createCompleteMessage({ id: args.subscriptionId }))
584
+ this.#endSubscription(connection, args.subscriptionId)
585
+ }
586
+
587
+ /**
588
+ * Drop this transport's subscribers and active subscriptions from the
589
+ * sessions it participates in. The sessions themselves are left intact:
590
+ * they are shared with the other transports of the same connection and
591
+ * own the protocol listeners for as long as the client stays connected.
592
+ *
593
+ * @note This method is invoked automatically when the handlers
594
+ * controller resets the handlers (e.g. `server.resetHandlers()`).
595
+ */
596
+ public reset(): void {
597
+ for (const connection of connections.values()) {
598
+ let ownsConnection = false
599
+
600
+ for (const [handler, entry] of connection.subscribers) {
601
+ if (entry.transport === this) {
602
+ connection.subscribers.delete(handler)
603
+ ownsConnection = true
604
+ }
605
+ }
606
+
607
+ // Resetting the handlers detaches the resolvers from their
608
+ // subscriptions, so run their cleanups instead of dropping them.
609
+ if (ownsConnection) {
610
+ this.#endAllSubscriptions(connection)
611
+ }
612
+ }
613
+ }
614
+
615
+ /**
616
+ * Forget the sessions of this transport, ending their subscriptions.
617
+ * @note This method is invoked automatically when the network is
618
+ * disabled (e.g. `server.close()`).
619
+ */
620
+ public dispose(): MaybePromise<void> {
621
+ const pendingCleanups: Array<Promise<void>> = []
622
+
623
+ for (const [clientId, connection] of connections) {
624
+ for (const [handler, entry] of connection.subscribers) {
625
+ if (entry.transport === this) {
626
+ connection.subscribers.delete(handler)
627
+ }
628
+ }
629
+
630
+ // A session is shared by all the transports of the same endpoint,
631
+ // so it's only torn down once the last of them is disposed of.
632
+ if (connection.subscribers.size === 0) {
633
+ pendingCleanups.push(this.#endAllSubscriptions(connection))
634
+ connections.delete(clientId)
635
+ }
636
+ }
637
+
638
+ if (pendingCleanups.length > 0) {
639
+ return Promise.all(pendingCleanups).then(() => {})
640
+ }
641
+ }
642
+
643
+ /**
644
+ * @note The transport is the sole owner of logging for GraphQL
645
+ * subscription connections. It logs parsed `graphql-transport-ws`
646
+ * frames instead of raw WebSocket messages.
647
+ */
648
+ public log(connection: WebSocketConnectionEventData): () => void {
649
+ return attachGraphQLSubscriptionLogger(connection)
650
+ }
651
+
652
+ protected [kConnect](connection: WebSocketHandlerConnection): boolean {
653
+ this.#getOrCreateConnection(connection)
654
+ return true
655
+ }
656
+
657
+ #getOrCreateConnection(
658
+ connection: WebSocketHandlerConnection,
659
+ ): GraphQLSubscriptionConnection {
660
+ const { client } = connection
661
+ const existingConnection = connections.get(client.id)
662
+
663
+ if (existingConnection) {
664
+ return existingConnection
665
+ }
666
+
667
+ const transportConnection: GraphQLSubscriptionConnection = {
668
+ client: connection.client,
669
+ server: connection.server,
670
+ subscribers: new Map(),
671
+ subscriptions: new Map(),
672
+ }
673
+ connections.set(client.id, transportConnection)
674
+
675
+ // Bind the protocol listeners alongside the session that owns them.
676
+ // Creating the session and binding its listeners is a single step, so
677
+ // they are guaranteed to be bound exactly once per connection no matter
678
+ // how many transports end up sharing this session.
679
+ client.addEventListener('message', (event) => {
680
+ this.#handleClientMessage(client.id, event.data)
681
+ })
682
+
683
+ client.addEventListener('close', () => {
684
+ // The resolvers can no longer affect any of the subscriptions
685
+ // on this connection once the client disconnects.
686
+ this.#endAllSubscriptions(transportConnection)
687
+ connections.delete(client.id)
688
+ })
689
+
690
+ return transportConnection
691
+ }
692
+
693
+ #getConnectionForSubscription(args: {
694
+ clientId: string
695
+ subscriptionId: string
696
+ intent: string
697
+ }): GraphQLSubscriptionConnection | undefined {
698
+ const connection = connections.get(args.clientId)
699
+
700
+ if (!connection || !connection.subscriptions.has(args.subscriptionId)) {
701
+ devUtils.warn(
702
+ 'Failed to %s the GraphQL subscription "%s": the subscription is no longer active.',
703
+ args.intent,
704
+ args.subscriptionId,
705
+ )
706
+ return undefined
707
+ }
708
+
709
+ return connection
710
+ }
711
+
712
+ #handleClientMessage(clientId: string, data: WebSocketData): void {
713
+ const connection = connections.get(clientId)
714
+
715
+ if (!connection) {
716
+ return
717
+ }
718
+
719
+ const message =
720
+ parseGraphQLWebSocketMessage<GraphQLWebSocketClientMessage>(data)
721
+
722
+ if (!message) {
723
+ return
724
+ }
725
+
726
+ switch (message.type) {
727
+ case 'connection_init': {
728
+ // Preserve the initialization payload (e.g. the client's
729
+ // credentials) so passthrough can replay it to the server.
730
+ connection.connectionParams = message.payload
731
+ connection.client.send(createAcknowledgeMessage())
732
+ break
733
+ }
734
+
735
+ case 'ping': {
736
+ connection.client.send(createPongMessage())
737
+ break
738
+ }
739
+
740
+ case 'subscribe': {
741
+ this.#handleSubscribeMessage(connection, message)
742
+ break
743
+ }
744
+
745
+ case 'complete': {
746
+ this.#endSubscription(connection, message.id)
747
+ break
748
+ }
749
+ }
750
+ }
751
+
752
+ #handleSubscribeMessage(
753
+ connection: GraphQLSubscriptionConnection,
754
+ message: GraphQLWebSocketSubscribeMessage,
755
+ ): void {
756
+ let node: ParsedGraphQLQuery
757
+
758
+ try {
759
+ node = parseDocumentNode(
760
+ parse(message.payload.query),
761
+ message.payload.operationName,
762
+ )
763
+ } catch (error) {
764
+ devUtils.warn(
765
+ 'Failed to intercept a GraphQL subscription to "%s": the subscription query is not a valid GraphQL document.\n\n%s',
766
+ toPublicUrl(connection.client.url),
767
+ error,
768
+ )
769
+ return
770
+ }
771
+
772
+ if (node.operationType !== OperationTypeNode.SUBSCRIPTION) {
773
+ devUtils.warn(
774
+ 'Intercepted a GraphQL %s "%s" over WebSocket: only subscription operations are supported over the WebSocket transport.',
775
+ node.operationType,
776
+ node.operationName || '(anonymous)',
777
+ )
778
+ return
779
+ }
780
+
781
+ // Register the subscription before dispatching it so the resolver
782
+ // can publish to it synchronously.
783
+ connection.subscriptions.set(message.id, [])
784
+
785
+ for (const { subscriber } of connection.subscribers.values()) {
786
+ if (subscriber({ node, message })) {
787
+ this.#emitSubscriptionEvent(connection, node, message)
788
+ return
789
+ }
790
+ }
791
+
792
+ devUtils.warn(
793
+ 'Intercepted a GraphQL subscription "%s" to "%s" that has no matching subscription handler. If you wish to mock this subscription, create a subscription handler for it.',
794
+ node.operationName || '(anonymous)',
795
+ toPublicUrl(connection.client.url),
796
+ )
797
+ }
798
+
799
+ /**
800
+ * Emit the "graphql:subscription" life-cycle event on the network.
801
+ * The event is emitted once the subscription has been established:
802
+ * matched by a subscription handler and resolved.
803
+ */
804
+ #emitSubscriptionEvent(
805
+ connection: GraphQLSubscriptionConnection,
806
+ node: ParsedGraphQLQuery,
807
+ message: GraphQLWebSocketSubscribeMessage,
808
+ ): void {
809
+ // Anonymous subscriptions can never match a subscription handler.
810
+ if (!connection.events || !node.operationName) {
811
+ return
812
+ }
813
+
814
+ connection.events.emit(
815
+ new GraphQLSubscriptionEvent({
816
+ operationName: node.operationName,
817
+ query: message.payload.query,
818
+ variables: { ...message.payload.variables },
819
+ request: createUpgradeRequest(connection.client.url),
820
+ }),
821
+ )
822
+ }
823
+ }
824
+
825
+ export type GraphQLSubscriptionName<
826
+ Query extends GraphQLQuery = GraphQLQuery,
827
+ Variables extends GraphQLVariables = GraphQLVariables,
828
+ > = GraphQLHandlerNameSelector | DocumentTypeDecoration<Query, Variables>
829
+
830
+ export interface GraphQLSubscriptionResolverInfo<
831
+ Query extends GraphQLQuery = GraphQLQuery,
832
+ Variables extends GraphQLVariables = GraphQLVariables,
833
+ > {
834
+ /**
835
+ * Path parameters parsed from the WebSocket connection URL.
836
+ */
837
+ params: PathParams
838
+
839
+ /**
840
+ * The name of the intercepted operation.
841
+ */
842
+ operationName: string
843
+
844
+ /**
845
+ * Intercepted GraphQL subscription.
846
+ */
847
+ subscription: GraphQLSubscription<Query, Variables>
848
+
849
+ /**
850
+ * The request that established the WebSocket connection this
851
+ * subscription is multiplexed over.
852
+ */
853
+ request: Request
854
+
855
+ /**
856
+ * Schedule a cleanup to run once this subscription ends and the
857
+ * resolver can no longer affect it: it has been completed (by the mock,
858
+ * the client, or the original server), terminated with errors, or the
859
+ * client has disconnected.
860
+ *
861
+ * @example
862
+ * api.subscription('OnCommentAdded', ({ subscription, finalize }) => {
863
+ * const interval = setInterval(() => subscription.publish(payload), 1000)
864
+ * finalize(() => clearInterval(interval))
865
+ * })
866
+ */
867
+ finalize: ResponseResolverFinalizeFunction
868
+ }
869
+
870
+ export type GraphQLSubscriptionResolver<
871
+ Query extends GraphQLQuery = GraphQLQuery,
872
+ Variables extends GraphQLVariables = GraphQLVariables,
873
+ > = (info: GraphQLSubscriptionResolverInfo<Query, Variables>) => void
874
+
875
+ export interface GraphQLSubscriptionHandlerOptions {
876
+ /**
877
+ * Mark this handler as used after its first match.
878
+ * Used handlers do not match subsequent subscriptions.
879
+ */
880
+ once?: boolean
881
+ }
882
+
883
+ /**
884
+ * A WebSocket handler intercepting GraphQL subscriptions by their
885
+ * operation name. Matching and resolution are delegated to it by the
886
+ * subscription transport (its sibling handler) so the first matching
887
+ * handler wins, respecting runtime handler overrides.
888
+ */
889
+ export class GraphQLSubscriptionHandler<
890
+ Query extends GraphQLQuery = GraphQLQuery,
891
+ Variables extends GraphQLVariables = GraphQLVariables,
892
+ > extends GraphQLWebSocketHandler {
893
+ public info: GraphQLHandlerInfo
894
+ public isUsed: boolean
895
+
896
+ readonly #operationName: string | RegExp
897
+ readonly #transport: GraphQLSubscriptionTransportHandler
898
+ readonly #resolver: GraphQLSubscriptionResolver<Query, Variables>
899
+ readonly #options: GraphQLSubscriptionHandlerOptions
900
+
901
+ constructor(args: {
902
+ url: Path
903
+ operationName: GraphQLSubscriptionName<Query, Variables>
904
+ transport: GraphQLSubscriptionTransportHandler
905
+ resolver: GraphQLSubscriptionResolver<Query, Variables>
906
+ options?: GraphQLSubscriptionHandlerOptions
907
+ }) {
908
+ super(args.url)
909
+
910
+ // Create the same GraphQL handler info as request-based GraphQL
911
+ // handlers so this handler prints nicely during introspection
912
+ // (e.g. `server.listHandlers()`). This also normalizes `DocumentNode`
913
+ // and typed document predicates to plain operation names.
914
+ this.info = GraphQLHandler.parseGraphQLRequestInfo({
915
+ operationType: OperationTypeNode.SUBSCRIPTION,
916
+ predicate: args.operationName,
917
+ url: args.url,
918
+ })
919
+
920
+ const { operationName } = this.info
921
+
922
+ invariant(
923
+ typeof operationName !== 'function' && !isDocumentNode(operationName),
924
+ 'Failed to create a GraphQL subscription handler: custom predicates are not supported for subscriptions',
925
+ )
926
+
927
+ this.#operationName = operationName
928
+ this.#transport = args.transport
929
+ this.#resolver = args.resolver
930
+ this.#options = args.options || {}
931
+ this.isUsed = false
932
+ }
933
+
934
+ public reset(): void {
935
+ this.isUsed = false
936
+ }
937
+
938
+ /**
939
+ * @note Individual subscription handlers stay silent. The subscription
940
+ * transport owns the GraphQL-aware logging for the entire connection
941
+ * (a logger is attached once per matching handler otherwise).
942
+ */
943
+ public log(): () => void {
944
+ return function detachLogger() {}
945
+ }
946
+
947
+ protected [kConnect](connection: WebSocketHandlerConnection): boolean {
948
+ this.#transport.subscribe(connection, this, (args) => {
949
+ return this.#handleSubscribe(connection, args)
950
+ })
951
+
952
+ return true
953
+ }
954
+
955
+ #handleSubscribe(
956
+ connection: WebSocketHandlerConnection,
957
+ args: {
958
+ node: ParsedGraphQLQuery
959
+ message: GraphQLWebSocketSubscribeMessage
960
+ },
961
+ ): boolean {
962
+ if (this.#options.once && this.isUsed) {
963
+ return false
964
+ }
965
+
966
+ const { operationName } = args.node
967
+
968
+ if (!operationName || !this.#matchesOperationName(operationName)) {
969
+ return false
970
+ }
971
+
972
+ this.isUsed = true
973
+
974
+ const subscription = new GraphQLSubscription<Query, Variables>({
975
+ message: args.message,
976
+ clientId: connection.client.id,
977
+ transport: this.#transport,
978
+ })
979
+
980
+ this.#resolver({
981
+ params: connection.params,
982
+ operationName,
983
+ subscription,
984
+ request: createUpgradeRequest(connection.client.url),
985
+ finalize: (cleanup) => {
986
+ this.#transport.finalize({
987
+ clientId: connection.client.id,
988
+ subscriptionId: subscription.id,
989
+ cleanup,
990
+ })
991
+ },
992
+ })
993
+
994
+ return true
995
+ }
996
+
997
+ #matchesOperationName(operationName: string): boolean {
998
+ if (this.#operationName instanceof RegExp) {
999
+ return this.#operationName.test(operationName)
1000
+ }
1001
+
1002
+ return this.#operationName === operationName
1003
+ }
1004
+ }
1005
+
1006
+ /**
1007
+ * Representation of the intercepted GraphQL subscription.
1008
+ */
1009
+ export class GraphQLSubscription<
1010
+ Query extends GraphQLQuery = GraphQLQuery,
1011
+ Variables extends GraphQLVariables = GraphQLVariables,
1012
+ > {
1013
+ public id: string
1014
+ public query: string
1015
+ public variables: Variables
1016
+ public extensions?: Record<string, unknown>
1017
+
1018
+ readonly #message: GraphQLWebSocketSubscribeMessage
1019
+ readonly #clientId: string
1020
+ readonly #transport: GraphQLSubscriptionTransportHandler
1021
+
1022
+ constructor(args: {
1023
+ message: GraphQLWebSocketSubscribeMessage
1024
+ clientId: string
1025
+ transport: GraphQLSubscriptionTransportHandler
1026
+ }) {
1027
+ this.id = args.message.id
1028
+ this.query = args.message.payload.query
1029
+ this.variables = (args.message.payload.variables || {}) as Variables
1030
+ this.extensions = args.message.payload.extensions
1031
+
1032
+ this.#message = args.message
1033
+ this.#clientId = args.clientId
1034
+ this.#transport = args.transport
1035
+ }
1036
+
1037
+ /**
1038
+ * Publish an execution result to the subscribed client.
1039
+ *
1040
+ * @example
1041
+ * subscription.publish({
1042
+ * data: {
1043
+ * postAdded: {
1044
+ * id: 'abc-123'
1045
+ * }
1046
+ * }
1047
+ * })
1048
+ */
1049
+ public publish(payload: GraphQLSubscriptionPayload<Query>): void {
1050
+ this.#transport.publish({
1051
+ clientId: this.#clientId,
1052
+ subscriptionId: this.id,
1053
+ payload,
1054
+ })
1055
+ }
1056
+
1057
+ /**
1058
+ * Use the given `Iterable` or `AsyncIterable` as the source
1059
+ * of data for this subscription. Whenever the iterable yields a
1060
+ * value, it gets published to this subscription.
1061
+ *
1062
+ * @example
1063
+ * subscription.from(async function* () {
1064
+ * yield { text: 'hello world' }
1065
+ * })
1066
+ */
1067
+ public async from(
1068
+ source: Iterable<Query> | AsyncIterable<Query>,
1069
+ ): Promise<void> {
1070
+ for await (const data of source) {
1071
+ this.publish({ data })
1072
+ }
1073
+ }
1074
+
1075
+ /**
1076
+ * Terminate this subscription with the given errors.
1077
+ *
1078
+ * @example
1079
+ * subscription.error([{ message: 'Something went wrong' }])
1080
+ */
1081
+ public error(errors: ReadonlyArray<Partial<GraphQLError>>): void {
1082
+ this.#transport.error({
1083
+ clientId: this.#clientId,
1084
+ subscriptionId: this.id,
1085
+ errors,
1086
+ })
1087
+ }
1088
+
1089
+ /**
1090
+ * Marks this subscription as complete.
1091
+ *
1092
+ * @example
1093
+ * subscription.complete()
1094
+ */
1095
+ public complete(): void {
1096
+ this.#transport.complete({
1097
+ clientId: this.#clientId,
1098
+ subscriptionId: this.id,
1099
+ })
1100
+ }
1101
+
1102
+ /**
1103
+ * Perform this GraphQL subscription as-is.
1104
+ * This establishes a connection to the actual server, replays
1105
+ * the intercepted subscription, and forwards the server payloads
1106
+ * to the GraphQL client. You can intercept, modify, or prevent
1107
+ * any of the original server messages.
1108
+ *
1109
+ * @example
1110
+ * const postAddedSubscription = subscription.passthrough()
1111
+ * postAddedSubscription.addEventListener('next', (event) => {
1112
+ * event.preventDefault()
1113
+ * event.data.payload.data.postAdded.id = 'mock-id'
1114
+ * subscription.publish(event.data.payload)
1115
+ * })
1116
+ */
1117
+ public passthrough(): GraphQLPassthroughSubscription {
1118
+ const connection = this.#transport.getConnection(this.#clientId)
1119
+
1120
+ /**
1121
+ * @note One can only call this method inside the GraphQL subscription
1122
+ * handler. By that point, the WebSocket connection has been established
1123
+ * and intercepted so the connection reference is guaranteed.
1124
+ */
1125
+ invariant(
1126
+ connection,
1127
+ 'Failed to passthrough the GraphQL subscription ("%s"): the underlying WebSocket connection is closed',
1128
+ this.query,
1129
+ )
1130
+
1131
+ return new GraphQLPassthroughSubscription({
1132
+ server: connection.server,
1133
+ message: this.#message,
1134
+ upstreamSession: ensureUpstreamSession(connection),
1135
+ onTerminate: () => {
1136
+ this.#transport.endSubscription({
1137
+ clientId: this.#clientId,
1138
+ subscriptionId: this.id,
1139
+ })
1140
+ },
1141
+ })
1142
+ }
1143
+ }
1144
+
1145
+ export type GraphQLPassthroughSubscriptionEventMap = {
1146
+ connection_ack: TypedEvent
1147
+ next: TypedEvent<GraphQLWebSocketNextMessage>
1148
+ error: TypedEvent<GraphQLWebSocketErrorMessage>
1149
+ complete: TypedEvent<GraphQLWebSocketCompleteMessage>
1150
+ }
1151
+
1152
+ /**
1153
+ * Representation of a GraphQL subscription to the actual server.
1154
+ * You interface with this object from the client's perspective.
1155
+ */
1156
+ export class GraphQLPassthroughSubscription {
1157
+ readonly #server: WebSocketServerHandle
1158
+ readonly #message: GraphQLWebSocketSubscribeMessage
1159
+ readonly #emitter: Emitter<GraphQLPassthroughSubscriptionEventMap>
1160
+ readonly #abortController: AbortController
1161
+ readonly #onTerminate: () => void
1162
+
1163
+ constructor(args: {
1164
+ server: WebSocketServerHandle
1165
+ message: GraphQLWebSocketSubscribeMessage
1166
+ upstreamSession: Promise<void>
1167
+ onTerminate: () => void
1168
+ }) {
1169
+ this.#server = args.server
1170
+ this.#message = args.message
1171
+ this.#onTerminate = args.onTerminate
1172
+ this.#emitter = new Emitter()
1173
+
1174
+ // An abort controller responsible for removing the server event
1175
+ // listeners once the subscription is unsubscribed.
1176
+ this.#abortController = new AbortController()
1177
+
1178
+ // Replay this subscription once the shared upstream session is
1179
+ // established, so the server can authorize this client first.
1180
+ args.upstreamSession.then(() => {
1181
+ if (!this.#abortController.signal.aborted) {
1182
+ this.#server.send(JSON.stringify(this.#message))
1183
+ }
1184
+ })
1185
+
1186
+ this.#server.addEventListener(
1187
+ 'message',
1188
+ (event) => {
1189
+ const message =
1190
+ parseGraphQLWebSocketMessage<GraphQLWebSocketServerMessage>(
1191
+ event.data,
1192
+ )
1193
+
1194
+ if (!message) {
1195
+ return
1196
+ }
1197
+
1198
+ switch (message.type) {
1199
+ case 'connection_ack': {
1200
+ event.preventDefault()
1201
+ this.#emitter.emit(new TypedEvent('connection_ack'))
1202
+ break
1203
+ }
1204
+
1205
+ case 'next': {
1206
+ if (message.id !== this.#message.id) {
1207
+ break
1208
+ }
1209
+
1210
+ const nextEvent = new TypedEvent('next', { data: message })
1211
+ this.#emitter.emit(nextEvent)
1212
+
1213
+ if (nextEvent.defaultPrevented) {
1214
+ event.preventDefault()
1215
+ }
1216
+
1217
+ break
1218
+ }
1219
+
1220
+ case 'error': {
1221
+ if (message.id !== this.#message.id) {
1222
+ break
1223
+ }
1224
+
1225
+ const errorEvent = new TypedEvent('error', { data: message })
1226
+ this.#emitter.emit(errorEvent)
1227
+
1228
+ if (errorEvent.defaultPrevented) {
1229
+ event.preventDefault()
1230
+ break
1231
+ }
1232
+
1233
+ // The original server terminated the subscription and that
1234
+ // frame reaches the client, so the subscription ends here.
1235
+ // A prevented frame means the mock took over instead.
1236
+ this.#onTerminate()
1237
+ break
1238
+ }
1239
+
1240
+ case 'complete': {
1241
+ if (message.id !== this.#message.id) {
1242
+ break
1243
+ }
1244
+
1245
+ const completeEvent = new TypedEvent('complete', { data: message })
1246
+ this.#emitter.emit(completeEvent)
1247
+
1248
+ if (completeEvent.defaultPrevented) {
1249
+ event.preventDefault()
1250
+ break
1251
+ }
1252
+
1253
+ this.#onTerminate()
1254
+ break
1255
+ }
1256
+ }
1257
+ },
1258
+ { signal: this.#abortController.signal },
1259
+ )
1260
+ }
1261
+
1262
+ /**
1263
+ * Add an event listener to the given GraphQL subscription event.
1264
+ *
1265
+ * @example
1266
+ * const onPostAddedSubscription = subscription.passthrough()
1267
+ * onPostAddedSubscription.addEventListener('next', (event) => {
1268
+ * console.log(event.data)
1269
+ * // { id, payload, ... }
1270
+ * })
1271
+ */
1272
+ public addEventListener<
1273
+ EventType extends keyof GraphQLPassthroughSubscriptionEventMap & string,
1274
+ >(
1275
+ event: EventType,
1276
+ listener: Emitter.Listener<
1277
+ Emitter<GraphQLPassthroughSubscriptionEventMap>,
1278
+ EventType
1279
+ >,
1280
+ ): void {
1281
+ this.#emitter.on(event, listener, {
1282
+ signal: this.#abortController.signal,
1283
+ })
1284
+ }
1285
+
1286
+ /**
1287
+ * Unsubscribe from this passthrough GraphQL subscription.
1288
+ * This stops this subscription on the original server.
1289
+ *
1290
+ * @note Unsubscribing from the original subscription has no
1291
+ * effect on the intercepted `subscription` object.
1292
+ *
1293
+ * @example
1294
+ * const onPostAddedSubscription = subscription.passthrough()
1295
+ * onPostAddedSubscription.unsubscribe()
1296
+ */
1297
+ public unsubscribe(): void {
1298
+ this.#abortController.abort()
1299
+ this.#emitter.removeAllListeners()
1300
+
1301
+ /**
1302
+ * @note Complete this subscription instead of closing the server
1303
+ * connection. That connection is shared by every subscription of
1304
+ * this client, and closing it would terminate the unrelated ones.
1305
+ */
1306
+ this.#server.send(createCompleteMessage({ id: this.#message.id }))
1307
+ }
1308
+ }
1309
+
1310
+ function logGraphQLFrame(args: {
1311
+ color: string
1312
+ label: string
1313
+ payload?: unknown
1314
+ }): void {
1315
+ const timestamp = getTimestamp({ milliseconds: true })
1316
+
1317
+ if (typeof args.payload === 'undefined') {
1318
+ // eslint-disable-next-line no-console
1319
+ console.log(
1320
+ devUtils.formatMessage(`${timestamp} %c${args.label}%c`),
1321
+ `color:${args.color}`,
1322
+ 'color:inherit',
1323
+ )
1324
+ return
1325
+ }
1326
+
1327
+ console.groupCollapsed(
1328
+ devUtils.formatMessage(`${timestamp} %c${args.label}%c`),
1329
+ `color:${args.color}`,
1330
+ 'color:inherit',
1331
+ )
1332
+ // eslint-disable-next-line no-console
1333
+ console.log(args.payload)
1334
+ console.groupEnd()
1335
+ }
1336
+
1337
+ /**
1338
+ * Attach a GraphQL-aware logger to the intercepted WebSocket connection.
1339
+ * Unlike the raw WebSocket logger, this logger prints parsed
1340
+ * `graphql-transport-ws` frames relevant to the subscription.
1341
+ */
1342
+ function attachGraphQLSubscriptionLogger(
1343
+ connection: WebSocketConnectionEventData,
1344
+ ): () => void {
1345
+ const { client } = connection
1346
+ const abortController = new AbortController()
1347
+
1348
+ logGraphQLFrame({
1349
+ color: colors.system,
1350
+ label: `GraphQL subscription connection ${toPublicUrl(client.url)}`,
1351
+ })
1352
+
1353
+ client.addEventListener(
1354
+ 'message',
1355
+ (event) => {
1356
+ const message =
1357
+ parseGraphQLWebSocketMessage<GraphQLWebSocketClientMessage>(event.data)
1358
+
1359
+ if (!message) {
1360
+ return
1361
+ }
1362
+
1363
+ switch (message.type) {
1364
+ case 'subscribe': {
1365
+ logGraphQLFrame({
1366
+ color: colors.outgoing,
1367
+ label: `subscribe (id: ${message.id})`,
1368
+ payload: message.payload,
1369
+ })
1370
+ break
1371
+ }
1372
+
1373
+ case 'complete': {
1374
+ logGraphQLFrame({
1375
+ color: colors.outgoing,
1376
+ label: `complete (id: ${message.id})`,
1377
+ })
1378
+ break
1379
+ }
1380
+ }
1381
+ },
1382
+ { signal: abortController.signal },
1383
+ )
1384
+
1385
+ // Proxy `client.send` to log the frames published to the client
1386
+ // (`client.send` does not dispatch any observable events).
1387
+ const originalClientSend = client.send
1388
+
1389
+ client.send = new Proxy(client.send, {
1390
+ apply: (target, thisArg, args) => {
1391
+ const [data] = args
1392
+ const message =
1393
+ parseGraphQLWebSocketMessage<GraphQLWebSocketServerMessage>(data)
1394
+
1395
+ if (message) {
1396
+ switch (message.type) {
1397
+ case 'next': {
1398
+ logGraphQLFrame({
1399
+ color: colors.mocked,
1400
+ label: `next (id: ${message.id})`,
1401
+ payload: message.payload,
1402
+ })
1403
+ break
1404
+ }
1405
+
1406
+ case 'error': {
1407
+ logGraphQLFrame({
1408
+ color: colors.mocked,
1409
+ label: `error (id: ${message.id})`,
1410
+ payload: message.payload,
1411
+ })
1412
+ break
1413
+ }
1414
+
1415
+ case 'complete': {
1416
+ logGraphQLFrame({
1417
+ color: colors.mocked,
1418
+ label: `complete (id: ${message.id})`,
1419
+ })
1420
+ break
1421
+ }
1422
+ }
1423
+ }
1424
+
1425
+ return Reflect.apply(target, thisArg, args)
1426
+ },
1427
+ })
1428
+
1429
+ return function detachLogger() {
1430
+ abortController.abort()
1431
+ client.send = originalClientSend
1432
+ }
1433
+ }
1434
+
1435
+ export type GraphQLSubscriptionHandlerFactory = <
1436
+ Query extends GraphQLQuery = GraphQLQuery,
1437
+ Variables extends GraphQLVariables = GraphQLVariables,
1438
+ >(
1439
+ operationName: GraphQLSubscriptionName<Query, Variables>,
1440
+ resolver: GraphQLSubscriptionResolver<Query, Variables>,
1441
+ options?: GraphQLSubscriptionHandlerOptions,
1442
+ ) => GraphQLSubscriptionHandler<Query, Variables>
1443
+
1444
+ /**
1445
+ * Create a `subscription()` handler factory bound to the given GraphQL
1446
+ * endpoint. All subscription handlers created by the factory share a single
1447
+ * subscription transport and a single WebSocket upgrade handler, both
1448
+ * attached to each handler as siblings.
1449
+ *
1450
+ * @example
1451
+ * const subscription = createGraphQLSubscriptionHandler('https://api.example.com/graphql')
1452
+ * subscription('OnPostAdded', ({ subscription }) => {
1453
+ * subscription.publish({ data: { postAdded: { id: 'abc-123' } } })
1454
+ * })
1455
+ */
1456
+ export function createGraphQLSubscriptionHandler(
1457
+ url: Path,
1458
+ ): GraphQLSubscriptionHandlerFactory {
1459
+ const webSocketUrl =
1460
+ typeof url === 'string' ? url.replace(/^http/, 'ws') : url
1461
+
1462
+ const transport = new GraphQLSubscriptionTransportHandler(webSocketUrl)
1463
+
1464
+ // The `upgrade` request handler enables WebSocket interception in Node.js.
1465
+ // The same handler instance is shared between all subscription handlers
1466
+ // of this endpoint (sibling handlers are deduped by reference).
1467
+ const upgradeHandler = http.get(({ request }) => {
1468
+ return (
1469
+ request.headers.get('upgrade')?.toLowerCase() === 'websocket' &&
1470
+ includesGraphQLProtocol(request.headers.get('sec-websocket-protocol')) &&
1471
+ matchRequestUrl(new URL(resolveWebSocketUrl(request.url)), webSocketUrl)
1472
+ .matches
1473
+ )
1474
+ }, webSocketUpgrade)
1475
+
1476
+ return (operationName, resolver, options) => {
1477
+ const handler = new GraphQLSubscriptionHandler({
1478
+ url: webSocketUrl,
1479
+ operationName,
1480
+ transport,
1481
+ resolver,
1482
+ options,
1483
+ })
1484
+
1485
+ return attachSiblingHandlers(handler, [transport, upgradeHandler])
1486
+ }
1487
+ }