msw 2.3.0-ws.rc-6 → 2.3.1

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 (208) hide show
  1. package/README.md +3 -9
  2. package/cli/init.js +0 -0
  3. package/config/scripts/postinstall.js +0 -0
  4. package/lib/browser/index.d.mts +6 -7
  5. package/lib/browser/index.d.ts +6 -7
  6. package/lib/browser/index.js +156 -83
  7. package/lib/browser/index.js.map +1 -1
  8. package/lib/browser/index.mjs +156 -83
  9. package/lib/browser/index.mjs.map +1 -1
  10. package/lib/core/{GraphQLHandler-DGyzNtRQ.d.ts → GraphQLHandler-COiPfZ8k.d.ts} +1 -1
  11. package/lib/core/{GraphQLHandler-CzcXr7At.d.mts → GraphQLHandler-Dq_WRbKe.d.mts} +1 -1
  12. package/lib/core/{HttpResponse-BOzDwzB6.d.ts → HttpResponse-B07UKAkU.d.ts} +2 -2
  13. package/lib/core/{HttpResponse-CSyJ1cbO.d.mts → HttpResponse-C7niBMwb.d.mts} +2 -2
  14. package/lib/core/HttpResponse.d.mts +1 -1
  15. package/lib/core/HttpResponse.d.ts +1 -1
  16. package/lib/core/SetupApi.d.mts +12 -15
  17. package/lib/core/SetupApi.d.ts +12 -15
  18. package/lib/core/SetupApi.js +1 -3
  19. package/lib/core/SetupApi.js.map +1 -1
  20. package/lib/core/SetupApi.mjs +1 -3
  21. package/lib/core/SetupApi.mjs.map +1 -1
  22. package/lib/core/getResponse.d.mts +1 -1
  23. package/lib/core/getResponse.d.ts +1 -1
  24. package/lib/core/graphql.d.mts +2 -2
  25. package/lib/core/graphql.d.ts +2 -2
  26. package/lib/core/handlers/GraphQLHandler.d.mts +2 -2
  27. package/lib/core/handlers/GraphQLHandler.d.ts +2 -2
  28. package/lib/core/handlers/HttpHandler.d.mts +1 -1
  29. package/lib/core/handlers/HttpHandler.d.ts +1 -1
  30. package/lib/core/handlers/RequestHandler.d.mts +1 -1
  31. package/lib/core/handlers/RequestHandler.d.ts +1 -1
  32. package/lib/core/http.d.mts +1 -1
  33. package/lib/core/http.d.ts +1 -1
  34. package/lib/core/index.d.mts +2 -5
  35. package/lib/core/index.d.ts +2 -5
  36. package/lib/core/index.js +1 -5
  37. package/lib/core/index.js.map +1 -1
  38. package/lib/core/index.mjs +1 -7
  39. package/lib/core/index.mjs.map +1 -1
  40. package/lib/core/passthrough.d.mts +1 -1
  41. package/lib/core/passthrough.d.ts +1 -1
  42. package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
  43. package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
  44. package/lib/core/utils/executeHandlers.d.mts +1 -1
  45. package/lib/core/utils/executeHandlers.d.ts +1 -1
  46. package/lib/core/utils/executeHandlers.js +0 -4
  47. package/lib/core/utils/executeHandlers.js.map +1 -1
  48. package/lib/core/utils/executeHandlers.mjs +0 -6
  49. package/lib/core/utils/executeHandlers.mjs.map +1 -1
  50. package/lib/core/utils/handleRequest.d.mts +2 -2
  51. package/lib/core/utils/handleRequest.d.ts +2 -2
  52. package/lib/core/utils/handleRequest.js.map +1 -1
  53. package/lib/core/utils/handleRequest.mjs.map +1 -1
  54. package/lib/core/utils/internal/Disposable.d.mts +2 -2
  55. package/lib/core/utils/internal/Disposable.d.ts +2 -2
  56. package/lib/core/utils/internal/Disposable.js +5 -2
  57. package/lib/core/utils/internal/Disposable.js.map +1 -1
  58. package/lib/core/utils/internal/Disposable.mjs +5 -2
  59. package/lib/core/utils/internal/Disposable.mjs.map +1 -1
  60. package/lib/core/utils/internal/devUtils.d.mts +10 -1
  61. package/lib/core/utils/internal/devUtils.d.ts +10 -1
  62. package/lib/core/utils/internal/devUtils.js +7 -0
  63. package/lib/core/utils/internal/devUtils.js.map +1 -1
  64. package/lib/core/utils/internal/devUtils.mjs +7 -0
  65. package/lib/core/utils/internal/devUtils.mjs.map +1 -1
  66. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +2 -2
  67. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +2 -2
  68. package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
  69. package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
  70. package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
  71. package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
  72. package/lib/core/utils/logging/getTimestamp.d.mts +1 -4
  73. package/lib/core/utils/logging/getTimestamp.d.ts +1 -4
  74. package/lib/core/utils/logging/getTimestamp.js +2 -6
  75. package/lib/core/utils/logging/getTimestamp.js.map +1 -1
  76. package/lib/core/utils/logging/getTimestamp.mjs +2 -6
  77. package/lib/core/utils/logging/getTimestamp.mjs.map +1 -1
  78. package/lib/core/utils/matching/matchRequestUrl.d.mts +1 -2
  79. package/lib/core/utils/matching/matchRequestUrl.d.ts +1 -2
  80. package/lib/core/utils/matching/matchRequestUrl.js +0 -4
  81. package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
  82. package/lib/core/utils/matching/matchRequestUrl.mjs +0 -4
  83. package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
  84. package/lib/core/utils/matching/normalizePath.d.mts +1 -0
  85. package/lib/core/utils/matching/normalizePath.d.ts +1 -0
  86. package/lib/core/utils/matching/normalizePath.js.map +1 -1
  87. package/lib/core/utils/matching/normalizePath.mjs.map +1 -1
  88. package/lib/core/utils/request/onUnhandledRequest.js +3 -3
  89. package/lib/core/utils/request/onUnhandledRequest.js.map +1 -1
  90. package/lib/core/utils/request/onUnhandledRequest.mjs +4 -4
  91. package/lib/core/utils/request/onUnhandledRequest.mjs.map +1 -1
  92. package/lib/core/utils/url/cleanUrl.d.mts +2 -1
  93. package/lib/core/utils/url/cleanUrl.d.ts +2 -1
  94. package/lib/core/utils/url/cleanUrl.js +3 -0
  95. package/lib/core/utils/url/cleanUrl.js.map +1 -1
  96. package/lib/core/utils/url/cleanUrl.mjs +3 -0
  97. package/lib/core/utils/url/cleanUrl.mjs.map +1 -1
  98. package/lib/iife/index.js +180 -1103
  99. package/lib/iife/index.js.map +1 -1
  100. package/lib/mockServiceWorker.js +1 -1
  101. package/lib/native/index.d.mts +5 -6
  102. package/lib/native/index.d.ts +5 -6
  103. package/lib/native/index.js +5 -13
  104. package/lib/native/index.js.map +1 -1
  105. package/lib/native/index.mjs +6 -14
  106. package/lib/native/index.mjs.map +1 -1
  107. package/lib/node/index.d.mts +7 -8
  108. package/lib/node/index.d.ts +7 -8
  109. package/lib/node/index.js +5 -13
  110. package/lib/node/index.js.map +1 -1
  111. package/lib/node/index.mjs +6 -14
  112. package/lib/node/index.mjs.map +1 -1
  113. package/package.json +36 -29
  114. package/src/browser/setupWorker/glossary.ts +10 -10
  115. package/src/browser/setupWorker/setupWorker.ts +3 -34
  116. package/src/browser/setupWorker/stop/createStop.ts +0 -4
  117. package/src/core/SetupApi.ts +20 -28
  118. package/src/core/index.ts +1 -8
  119. package/src/core/utils/executeHandlers.ts +2 -6
  120. package/src/core/utils/handleRequest.ts +2 -1
  121. package/src/core/utils/internal/Disposable.ts +6 -3
  122. package/src/core/utils/internal/devUtils.test.ts +21 -0
  123. package/src/core/utils/internal/devUtils.ts +13 -0
  124. package/src/core/utils/logging/getTimestamp.test.ts +6 -20
  125. package/src/core/utils/logging/getTimestamp.ts +6 -11
  126. package/src/core/utils/matching/matchRequestUrl.test.ts +8 -41
  127. package/src/core/utils/matching/matchRequestUrl.ts +0 -4
  128. package/src/core/utils/matching/normalizePath.test.ts +7 -1
  129. package/src/core/utils/matching/normalizePath.ts +1 -0
  130. package/src/core/utils/request/onUnhandledRequest.test.ts +30 -4
  131. package/src/core/utils/request/onUnhandledRequest.ts +4 -4
  132. package/src/core/utils/url/cleanUrl.test.ts +8 -3
  133. package/src/core/utils/url/cleanUrl.ts +9 -1
  134. package/src/core/utils/url/getAbsoluteUrl.node.test.ts +3 -3
  135. package/src/core/utils/url/getAbsoluteUrl.test.ts +5 -5
  136. package/src/core/utils/url/isAbsoluteUrl.test.ts +7 -7
  137. package/src/node/SetupServerApi.ts +7 -8
  138. package/src/node/SetupServerCommonApi.ts +8 -15
  139. package/src/node/glossary.ts +7 -5
  140. package/src/node/setupServer.ts +1 -2
  141. package/lib/core/handlers/WebSocketHandler.d.mts +0 -32
  142. package/lib/core/handlers/WebSocketHandler.d.ts +0 -32
  143. package/lib/core/handlers/WebSocketHandler.js +0 -62
  144. package/lib/core/handlers/WebSocketHandler.js.map +0 -1
  145. package/lib/core/handlers/WebSocketHandler.mjs +0 -44
  146. package/lib/core/handlers/WebSocketHandler.mjs.map +0 -1
  147. package/lib/core/ws/WebSocketClientManager.d.mts +0 -58
  148. package/lib/core/ws/WebSocketClientManager.d.ts +0 -58
  149. package/lib/core/ws/WebSocketClientManager.js +0 -162
  150. package/lib/core/ws/WebSocketClientManager.js.map +0 -1
  151. package/lib/core/ws/WebSocketClientManager.mjs +0 -142
  152. package/lib/core/ws/WebSocketClientManager.mjs.map +0 -1
  153. package/lib/core/ws/handleWebSocketEvent.d.mts +0 -16
  154. package/lib/core/ws/handleWebSocketEvent.d.ts +0 -16
  155. package/lib/core/ws/handleWebSocketEvent.js +0 -56
  156. package/lib/core/ws/handleWebSocketEvent.js.map +0 -1
  157. package/lib/core/ws/handleWebSocketEvent.mjs +0 -36
  158. package/lib/core/ws/handleWebSocketEvent.mjs.map +0 -1
  159. package/lib/core/ws/utils/attachWebSocketLogger.d.mts +0 -34
  160. package/lib/core/ws/utils/attachWebSocketLogger.d.ts +0 -34
  161. package/lib/core/ws/utils/attachWebSocketLogger.js +0 -217
  162. package/lib/core/ws/utils/attachWebSocketLogger.js.map +0 -1
  163. package/lib/core/ws/utils/attachWebSocketLogger.mjs +0 -197
  164. package/lib/core/ws/utils/attachWebSocketLogger.mjs.map +0 -1
  165. package/lib/core/ws/utils/getMessageLength.d.mts +0 -11
  166. package/lib/core/ws/utils/getMessageLength.d.ts +0 -11
  167. package/lib/core/ws/utils/getMessageLength.js +0 -33
  168. package/lib/core/ws/utils/getMessageLength.js.map +0 -1
  169. package/lib/core/ws/utils/getMessageLength.mjs +0 -13
  170. package/lib/core/ws/utils/getMessageLength.mjs.map +0 -1
  171. package/lib/core/ws/utils/getPublicData.d.mts +0 -5
  172. package/lib/core/ws/utils/getPublicData.d.ts +0 -5
  173. package/lib/core/ws/utils/getPublicData.js +0 -36
  174. package/lib/core/ws/utils/getPublicData.js.map +0 -1
  175. package/lib/core/ws/utils/getPublicData.mjs +0 -16
  176. package/lib/core/ws/utils/getPublicData.mjs.map +0 -1
  177. package/lib/core/ws/utils/truncateMessage.d.mts +0 -3
  178. package/lib/core/ws/utils/truncateMessage.d.ts +0 -3
  179. package/lib/core/ws/utils/truncateMessage.js +0 -31
  180. package/lib/core/ws/utils/truncateMessage.js.map +0 -1
  181. package/lib/core/ws/utils/truncateMessage.mjs +0 -11
  182. package/lib/core/ws/utils/truncateMessage.mjs.map +0 -1
  183. package/lib/core/ws/webSocketInterceptor.d.mts +0 -5
  184. package/lib/core/ws/webSocketInterceptor.d.ts +0 -5
  185. package/lib/core/ws/webSocketInterceptor.js +0 -26
  186. package/lib/core/ws/webSocketInterceptor.js.map +0 -1
  187. package/lib/core/ws/webSocketInterceptor.mjs +0 -6
  188. package/lib/core/ws/webSocketInterceptor.mjs.map +0 -1
  189. package/lib/core/ws.d.mts +0 -49
  190. package/lib/core/ws.d.ts +0 -49
  191. package/lib/core/ws.js +0 -65
  192. package/lib/core/ws.js.map +0 -1
  193. package/lib/core/ws.mjs +0 -48
  194. package/lib/core/ws.mjs.map +0 -1
  195. package/src/core/handlers/WebSocketHandler.ts +0 -71
  196. package/src/core/ws/WebSocketClientManager.test.ts +0 -157
  197. package/src/core/ws/WebSocketClientManager.ts +0 -234
  198. package/src/core/ws/handleWebSocketEvent.ts +0 -56
  199. package/src/core/ws/utils/attachWebSocketLogger.ts +0 -269
  200. package/src/core/ws/utils/getMessageLength.test.ts +0 -16
  201. package/src/core/ws/utils/getMessageLength.ts +0 -19
  202. package/src/core/ws/utils/getPublicData.test.ts +0 -38
  203. package/src/core/ws/utils/getPublicData.ts +0 -17
  204. package/src/core/ws/utils/truncateMessage.test.ts +0 -12
  205. package/src/core/ws/utils/truncateMessage.ts +0 -9
  206. package/src/core/ws/webSocketInterceptor.ts +0 -3
  207. package/src/core/ws.test.ts +0 -23
  208. package/src/core/ws.ts +0 -124
@@ -1,234 +0,0 @@
1
- import { invariant } from 'outvariant'
2
- import type {
3
- WebSocketData,
4
- WebSocketClientConnection,
5
- WebSocketClientConnectionProtocol,
6
- } from '@mswjs/interceptors/WebSocket'
7
- import { matchRequestUrl, type Path } from '../utils/matching/matchRequestUrl'
8
-
9
- export const MSW_WEBSOCKET_CLIENTS_KEY = 'msw:ws:clients'
10
-
11
- export type WebSocketBroadcastChannelMessage =
12
- | {
13
- type: 'extraneous:send'
14
- payload: {
15
- clientId: string
16
- data: WebSocketData
17
- }
18
- }
19
- | {
20
- type: 'extraneous:close'
21
- payload: {
22
- clientId: string
23
- code?: number
24
- reason?: string
25
- }
26
- }
27
-
28
- type SerializedClient = {
29
- clientId: string
30
- url: string
31
- }
32
-
33
- /**
34
- * A manager responsible for accumulating WebSocket client
35
- * connections across different browser runtimes.
36
- */
37
- export class WebSocketClientManager {
38
- private inMemoryClients: Set<WebSocketClientConnectionProtocol>
39
-
40
- constructor(
41
- private channel: BroadcastChannel,
42
- private url: Path,
43
- ) {
44
- this.inMemoryClients = new Set()
45
-
46
- if (typeof localStorage !== 'undefined') {
47
- // When the worker clears the local storage key in "worker.stop()",
48
- // also clear the in-memory clients map.
49
- localStorage.removeItem = new Proxy(localStorage.removeItem, {
50
- apply: (target, thisArg, args) => {
51
- const [key] = args
52
-
53
- if (key === MSW_WEBSOCKET_CLIENTS_KEY) {
54
- this.inMemoryClients.clear()
55
- }
56
-
57
- return Reflect.apply(target, thisArg, args)
58
- },
59
- })
60
- }
61
- }
62
-
63
- /**
64
- * All active WebSocket client connections.
65
- */
66
- get clients(): Set<WebSocketClientConnectionProtocol> {
67
- // In the browser, different runtimes use "localStorage"
68
- // as the shared source of all the clients.
69
- if (typeof localStorage !== 'undefined') {
70
- const inMemoryClients = Array.from(this.inMemoryClients)
71
-
72
- console.log('get clients()', inMemoryClients, this.getSerializedClients())
73
-
74
- return new Set(
75
- inMemoryClients.concat(
76
- this.getSerializedClients()
77
- // Filter out the serialized clients that are already present
78
- // in this runtime in-memory. This is crucial because a remote client
79
- // wrapper CANNOT send a message to the client in THIS runtime
80
- // (the "message" event on broadcast channel won't trigger).
81
- .filter((serializedClient) => {
82
- if (
83
- inMemoryClients.every(
84
- (client) => client.id !== serializedClient.clientId,
85
- )
86
- ) {
87
- return serializedClient
88
- }
89
- })
90
- .map((serializedClient) => {
91
- return new WebSocketRemoteClientConnection(
92
- serializedClient.clientId,
93
- new URL(serializedClient.url),
94
- this.channel,
95
- )
96
- }),
97
- ),
98
- )
99
- }
100
-
101
- // In Node.js, the manager acts as a singleton, and all clients
102
- // are kept in-memory.
103
- return this.inMemoryClients
104
- }
105
-
106
- private getSerializedClients(): Array<SerializedClient> {
107
- invariant(
108
- typeof localStorage !== 'undefined',
109
- 'Failed to call WebSocketClientManager#getSerializedClients() in a non-browser environment. This is likely a bug in MSW. Please, report it on GitHub: https://github.com/mswjs/msw',
110
- )
111
-
112
- const clientsJson = localStorage.getItem(MSW_WEBSOCKET_CLIENTS_KEY)
113
-
114
- if (!clientsJson) {
115
- return []
116
- }
117
-
118
- const allClients = JSON.parse(clientsJson) as Array<SerializedClient>
119
- const matchingClients = allClients.filter((client) => {
120
- return matchRequestUrl(new URL(client.url), this.url).matches
121
- })
122
-
123
- return matchingClients
124
- }
125
-
126
- private addClient(client: WebSocketClientConnection): void {
127
- this.inMemoryClients.add(client)
128
-
129
- if (typeof localStorage !== 'undefined') {
130
- const serializedClients = this.getSerializedClients()
131
-
132
- // Serialize the current client for other runtimes to create
133
- // a remote wrapper over it. This has no effect on the current runtime.
134
- const nextSerializedClients = serializedClients.concat({
135
- clientId: client.id,
136
- url: client.url.href,
137
- } as SerializedClient)
138
-
139
- localStorage.setItem(
140
- MSW_WEBSOCKET_CLIENTS_KEY,
141
- JSON.stringify(nextSerializedClients),
142
- )
143
- }
144
- }
145
-
146
- /**
147
- * Adds the given `WebSocket` client connection to the set
148
- * of all connections. The given connection is always the complete
149
- * connection object because `addConnection()` is called only
150
- * for the opened connections in the same runtime.
151
- */
152
- public addConnection(client: WebSocketClientConnection): void {
153
- this.addClient(client)
154
-
155
- // Instruct the current client how to handle events
156
- // coming from other runtimes (e.g. when calling `.broadcast()`).
157
- const handleExtraneousMessage = (
158
- message: MessageEvent<WebSocketBroadcastChannelMessage>,
159
- ) => {
160
- const { type, payload } = message.data
161
-
162
- // Ignore broadcasted messages for other clients.
163
- if (
164
- typeof payload === 'object' &&
165
- 'clientId' in payload &&
166
- payload.clientId !== client.id
167
- ) {
168
- return
169
- }
170
-
171
- switch (type) {
172
- case 'extraneous:send': {
173
- client.send(payload.data)
174
- break
175
- }
176
-
177
- case 'extraneous:close': {
178
- client.close(payload.code, payload.reason)
179
- break
180
- }
181
- }
182
- }
183
-
184
- const abortController = new AbortController()
185
-
186
- this.channel.addEventListener('message', handleExtraneousMessage, {
187
- signal: abortController.signal,
188
- })
189
-
190
- // Once closed, this connection cannot be operated on.
191
- // This must include the extraneous runtimes as well.
192
- client.addEventListener('close', () => abortController.abort(), {
193
- once: true,
194
- })
195
- }
196
- }
197
-
198
- /**
199
- * A wrapper class to operate with WebSocket client connections
200
- * from other runtimes. This class maintains 1-1 public API
201
- * compatibility to the `WebSocketClientConnection` but relies
202
- * on the given `BroadcastChannel` to communicate instructions
203
- * with the client connections from other runtimes.
204
- */
205
- export class WebSocketRemoteClientConnection
206
- implements WebSocketClientConnectionProtocol
207
- {
208
- constructor(
209
- public readonly id: string,
210
- public readonly url: URL,
211
- private channel: BroadcastChannel,
212
- ) {}
213
-
214
- send(data: WebSocketData): void {
215
- this.channel.postMessage({
216
- type: 'extraneous:send',
217
- payload: {
218
- clientId: this.id,
219
- data,
220
- },
221
- } as WebSocketBroadcastChannelMessage)
222
- }
223
-
224
- close(code?: number | undefined, reason?: string | undefined): void {
225
- this.channel.postMessage({
226
- type: 'extraneous:close',
227
- payload: {
228
- clientId: this.id,
229
- code,
230
- reason,
231
- },
232
- } as WebSocketBroadcastChannelMessage)
233
- }
234
- }
@@ -1,56 +0,0 @@
1
- import type { WebSocketConnectionData } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'
2
- import { RequestHandler } from '../handlers/RequestHandler'
3
- import { WebSocketHandler, kDispatchEvent } from '../handlers/WebSocketHandler'
4
- import { webSocketInterceptor } from './webSocketInterceptor'
5
-
6
- interface HandleWebSocketEventOptions {
7
- getHandlers: () => Array<RequestHandler | WebSocketHandler>
8
- onMockedConnection: (connection: WebSocketConnectionData) => void
9
- onPassthroughConnection: (onnection: WebSocketConnectionData) => void
10
- }
11
-
12
- export function handleWebSocketEvent(options: HandleWebSocketEventOptions) {
13
- webSocketInterceptor.on('connection', (connection) => {
14
- const handlers = options.getHandlers()
15
-
16
- const connectionEvent = new MessageEvent('connection', {
17
- data: connection,
18
- })
19
-
20
- // First, filter only those WebSocket handlers that
21
- // match the "ws.link()" endpoint predicate. Don't dispatch
22
- // anything yet so the logger can be attached to the connection
23
- // before it potentially sends events.
24
- const matchingHandlers = handlers.filter<WebSocketHandler>(
25
- (handler): handler is WebSocketHandler => {
26
- if (handler instanceof WebSocketHandler) {
27
- return handler.predicate({
28
- event: connectionEvent,
29
- parsedResult: handler.parse({
30
- event: connectionEvent,
31
- }),
32
- })
33
- }
34
-
35
- return false
36
- },
37
- )
38
-
39
- if (matchingHandlers.length > 0) {
40
- options?.onMockedConnection(connection)
41
-
42
- // Iterate over the handlers and forward the connection
43
- // event to WebSocket event handlers. This is equivalent
44
- // to dispatching that event onto multiple listeners.
45
- for (const handler of matchingHandlers) {
46
- handler[kDispatchEvent](connectionEvent)
47
- }
48
- } else {
49
- options?.onPassthroughConnection(connection)
50
-
51
- // If none of the "ws" handlers matched,
52
- // establish the WebSocket connection as-is.
53
- connection.server.connect()
54
- }
55
- })
56
- }
@@ -1,269 +0,0 @@
1
- import type {
2
- WebSocketClientConnection,
3
- WebSocketConnectionData,
4
- WebSocketData,
5
- } from '@mswjs/interceptors/WebSocket'
6
- import { devUtils } from '../../utils/internal/devUtils'
7
- import { getTimestamp } from '../../utils/logging/getTimestamp'
8
- import { toPublicUrl } from '../../utils/request/toPublicUrl'
9
- import { getMessageLength } from './getMessageLength'
10
- import { getPublicData } from './getPublicData'
11
-
12
- const colors = {
13
- blue: '#3b82f6',
14
- green: '#22c55e',
15
- red: '#ef4444',
16
- orange: '#ff6a33',
17
- }
18
-
19
- export function attachWebSocketLogger(
20
- connection: WebSocketConnectionData,
21
- ): void {
22
- const { client, server } = connection
23
-
24
- logConnectionOpen(client)
25
-
26
- // Log the events sent from the WebSocket client.
27
- // WebSocket client connection object is written from the
28
- // server's perspective so these message events are outgoing.
29
- /**
30
- * @todo Provide the reference to the exact event handler
31
- * that called this `client.send()`.
32
- */
33
- client.addEventListener('message', (event) => {
34
- logOutgoingClientMessage(event)
35
- })
36
-
37
- client.addEventListener('close', (event) => {
38
- logConnectionClose(event)
39
- })
40
-
41
- // Log the events received by the WebSocket client.
42
- // "client.socket" references the actual WebSocket instance
43
- // so these message events are incoming messages.
44
- client.socket.addEventListener('message', (event) => {
45
- logIncomingClientMessage(event)
46
- })
47
-
48
- // Log client errors (connection closures due to errors).
49
- client.socket.addEventListener('error', (event) => {
50
- logClientError(event)
51
- })
52
-
53
- client.send = new Proxy(client.send, {
54
- apply(target, thisArg, args) {
55
- const [data] = args
56
- const messageEvent = new MessageEvent('message', { data })
57
- Object.defineProperties(messageEvent, {
58
- currentTarget: {
59
- enumerable: true,
60
- writable: false,
61
- value: client.socket,
62
- },
63
- target: {
64
- enumerable: true,
65
- writable: false,
66
- value: client.socket,
67
- },
68
- })
69
- logIncomingMockedClientMessage(messageEvent)
70
-
71
- return Reflect.apply(target, thisArg, args)
72
- },
73
- })
74
-
75
- server.addEventListener(
76
- 'open',
77
- () => {
78
- server.addEventListener('message', (event) => {
79
- logIncomingServerMessage(event)
80
- })
81
- },
82
- { once: true },
83
- )
84
-
85
- // Log outgoing client events initiated by the event handler.
86
- // The actual client never sent these but the handler did.
87
- server.send = new Proxy(server.send, {
88
- apply(target, thisArg, args) {
89
- const [data] = args
90
- const messageEvent = new MessageEvent('message', { data })
91
- Object.defineProperties(messageEvent, {
92
- currentTarget: {
93
- enumerable: true,
94
- writable: false,
95
- value: server['realWebSocket'],
96
- },
97
- target: {
98
- enumerable: true,
99
- writable: false,
100
- value: server['realWebSocket'],
101
- },
102
- })
103
-
104
- logOutgoingMockedClientMessage(messageEvent)
105
-
106
- return Reflect.apply(target, thisArg, args)
107
- },
108
- })
109
- }
110
-
111
- /**
112
- * Prints the WebSocket connection.
113
- * This is meant to be logged by every WebSocket handler
114
- * that intercepted this connection. This helps you see
115
- * what handlers observe this connection.
116
- */
117
- export function logConnectionOpen(client: WebSocketClientConnection) {
118
- const publicUrl = toPublicUrl(client.url)
119
-
120
- console.groupCollapsed(
121
- devUtils.formatMessage(`${getTimestamp()} %c▶%c ${publicUrl}`),
122
- `color:${colors.blue}`,
123
- 'color:inherit',
124
- )
125
- console.log('Client:', client.socket)
126
- console.groupEnd()
127
- }
128
-
129
- /**
130
- * Prints the outgoing client message.
131
- */
132
- export async function logOutgoingClientMessage(
133
- event: MessageEvent<WebSocketData>,
134
- ) {
135
- const byteLength = getMessageLength(event.data)
136
- const publicData = await getPublicData(event.data)
137
-
138
- console.groupCollapsed(
139
- devUtils.formatMessage(
140
- `${getTimestamp({ milliseconds: true })} %c↑%c ${publicData} %c${byteLength}%c`,
141
- ),
142
- `color:${colors.green}`,
143
- 'color:inherit',
144
- 'color:gray;font-weight:normal',
145
- 'color:inherit;font-weight:inherit',
146
- )
147
- console.log(event)
148
- console.groupEnd()
149
- }
150
-
151
- /**
152
- * Prints the outgoing client message initiated
153
- * by `server.send()` in the event handler.
154
- */
155
- export async function logOutgoingMockedClientMessage(
156
- event: MessageEvent<WebSocketData>,
157
- ) {
158
- const byteLength = getMessageLength(event.data)
159
- const publicData = await getPublicData(event.data)
160
-
161
- console.groupCollapsed(
162
- devUtils.formatMessage(
163
- `${getTimestamp({ milliseconds: true })} %c⇡%c ${publicData} %c${byteLength}%c`,
164
- ),
165
- `color:${colors.orange}`,
166
- 'color:inherit',
167
- 'color:gray;font-weight:normal',
168
- 'color:inherit;font-weight:inherit',
169
- )
170
- console.log(event)
171
- console.groupEnd()
172
- }
173
-
174
- /**
175
- * Prings the message received by the WebSocket client.
176
- * This is fired when the "message" event is dispatched
177
- * on the actual WebSocket client instance, and translates to
178
- * the client receiving a message from the server.
179
- */
180
- export async function logIncomingClientMessage(
181
- event: MessageEvent<WebSocketData>,
182
- ) {
183
- const byteLength = getMessageLength(event.data)
184
- const publicData = await getPublicData(event.data)
185
-
186
- console.groupCollapsed(
187
- devUtils.formatMessage(
188
- `${getTimestamp({ milliseconds: true })} %c↓%c ${publicData} %c${byteLength}%c`,
189
- ),
190
- `color:${colors.red}`,
191
- 'color:inherit',
192
- 'color:gray;font-weight:normal',
193
- 'color:inherit;font-weight:inherit',
194
- )
195
- console.log(event)
196
- console.groupEnd()
197
- }
198
-
199
- /**
200
- * Prints the outgoing client message initiated
201
- * by `client.send()` in the event handler.
202
- */
203
- export async function logIncomingMockedClientMessage(
204
- event: MessageEvent<WebSocketData>,
205
- ) {
206
- const byteLength = getMessageLength(event.data)
207
- const publicData = await getPublicData(event.data)
208
-
209
- console.groupCollapsed(
210
- devUtils.formatMessage(
211
- `${getTimestamp({ milliseconds: true })} %c⇣%c ${publicData} %c${byteLength}%c`,
212
- ),
213
- `color:${colors.orange}`,
214
- 'color:inherit',
215
- 'color:gray;font-weight:normal',
216
- 'color:inherit;font-weight:inherit',
217
- )
218
- console.log(event)
219
- console.groupEnd()
220
- }
221
-
222
- function logConnectionClose(event: CloseEvent) {
223
- const target = event.target as WebSocket
224
- const publicUrl = toPublicUrl(target.url)
225
-
226
- console.groupCollapsed(
227
- devUtils.formatMessage(
228
- `${getTimestamp({ milliseconds: true })} %c■%c ${publicUrl}`,
229
- ),
230
- `color:${colors.blue}`,
231
- 'color:inherit',
232
- )
233
- console.log(event)
234
- console.groupEnd()
235
- }
236
-
237
- export async function logIncomingServerMessage(
238
- event: MessageEvent<WebSocketData>,
239
- ) {
240
- const byteLength = getMessageLength(event.data)
241
- const publicData = await getPublicData(event.data)
242
-
243
- console.groupCollapsed(
244
- devUtils.formatMessage(
245
- `${getTimestamp({ milliseconds: true })} %c⇣%c ${publicData} %c${byteLength}%c`,
246
- ),
247
- `color:${colors.green}`,
248
- 'color:inherit',
249
- 'color:gray;font-weight:normal',
250
- 'color:inherit;font-weight:inherit',
251
- )
252
- console.log(event)
253
- console.groupEnd()
254
- }
255
-
256
- function logClientError(event: Event) {
257
- const socket = event.target as WebSocket
258
- const publicUrl = toPublicUrl(socket.url)
259
-
260
- console.groupCollapsed(
261
- devUtils.formatMessage(
262
- `${getTimestamp({ milliseconds: true })} %c\u00D7%c ${publicUrl}`,
263
- ),
264
- `color:${colors.blue}`,
265
- 'color:inherit',
266
- )
267
- console.log(event)
268
- console.groupEnd()
269
- }
@@ -1,16 +0,0 @@
1
- import { getMessageLength } from './getMessageLength'
2
-
3
- it('returns the length of the string', () => {
4
- expect(getMessageLength('')).toBe(0)
5
- expect(getMessageLength('hello')).toBe(5)
6
- })
7
-
8
- it('returns the size of the Blob', () => {
9
- expect(getMessageLength(new Blob())).toBe(0)
10
- expect(getMessageLength(new Blob(['hello']))).toBe(5)
11
- })
12
-
13
- it('returns the byte length of ArrayBuffer', () => {
14
- expect(getMessageLength(new ArrayBuffer(0))).toBe(0)
15
- expect(getMessageLength(new ArrayBuffer(5))).toBe(5)
16
- })
@@ -1,19 +0,0 @@
1
- import type { WebSocketData } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'
2
-
3
- /**
4
- * Returns the byte length of the given WebSocket message.
5
- * @example
6
- * getMessageLength('hello') // 5
7
- * getMessageLength(new Blob(['hello'])) // 5
8
- */
9
- export function getMessageLength(data: WebSocketData): number {
10
- if (data instanceof Blob) {
11
- return data.size
12
- }
13
-
14
- if (data instanceof ArrayBuffer) {
15
- return data.byteLength
16
- }
17
-
18
- return new Blob([data]).size
19
- }
@@ -1,38 +0,0 @@
1
- import { getPublicData } from './getPublicData'
2
-
3
- it('returns a short string as-is', async () => {
4
- expect(await getPublicData('')).toBe('')
5
- expect(await getPublicData('hello')).toBe('hello')
6
- })
7
-
8
- it('returns a truncated long string', async () => {
9
- expect(await getPublicData('this is a very long string')).toBe(
10
- 'this is a very long stri…',
11
- )
12
- })
13
-
14
- it('returns a short Blob text as-is', async () => {
15
- expect(await getPublicData(new Blob(['']))).toBe('Blob()')
16
- expect(await getPublicData(new Blob(['hello']))).toBe('Blob(hello)')
17
- })
18
-
19
- it('returns a truncated long Blob text', async () => {
20
- expect(await getPublicData(new Blob(['this is a very long string']))).toBe(
21
- 'Blob(this is a very long stri…)',
22
- )
23
- })
24
-
25
- it('returns a short ArrayBuffer text as-is', async () => {
26
- expect(await getPublicData(new TextEncoder().encode(''))).toBe(
27
- 'ArrayBuffer()',
28
- )
29
- expect(await getPublicData(new TextEncoder().encode('hello'))).toBe(
30
- 'ArrayBuffer(hello)',
31
- )
32
- })
33
-
34
- it('returns a truncated ArrayBuffer text', async () => {
35
- expect(
36
- await getPublicData(new TextEncoder().encode('this is a very long string')),
37
- ).toBe('ArrayBuffer(this is a very long stri…)')
38
- })
@@ -1,17 +0,0 @@
1
- import { WebSocketData } from '@mswjs/interceptors/WebSocket'
2
- import { truncateMessage } from './truncateMessage'
3
-
4
- export async function getPublicData(data: WebSocketData): Promise<string> {
5
- if (data instanceof Blob) {
6
- const text = await data.text()
7
- return `Blob(${truncateMessage(text)})`
8
- }
9
-
10
- // Handle all ArrayBuffer-like objects.
11
- if (typeof data === 'object' && 'byteLength' in data) {
12
- const text = new TextDecoder().decode(data)
13
- return `ArrayBuffer(${truncateMessage(text)})`
14
- }
15
-
16
- return truncateMessage(data)
17
- }
@@ -1,12 +0,0 @@
1
- import { truncateMessage } from './truncateMessage'
2
-
3
- it('returns a short string as-is', () => {
4
- expect(truncateMessage('')).toBe('')
5
- expect(truncateMessage('hello')).toBe('hello')
6
- })
7
-
8
- it('truncates a long string', () => {
9
- expect(truncateMessage('this is a very long string')).toBe(
10
- 'this is a very long stri…',
11
- )
12
- })
@@ -1,9 +0,0 @@
1
- const MAX_LENGTH = 24
2
-
3
- export function truncateMessage(message: string): string {
4
- if (message.length <= MAX_LENGTH) {
5
- return message
6
- }
7
-
8
- return `${message.slice(0, MAX_LENGTH)}…`
9
- }
@@ -1,3 +0,0 @@
1
- import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'
2
-
3
- export const webSocketInterceptor = new WebSocketInterceptor()