msw 0.42.3 → 0.44.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.
@@ -2,22 +2,21 @@
2
2
  /* tslint:disable */
3
3
 
4
4
  /**
5
- * Mock Service Worker (0.42.3).
5
+ * Mock Service Worker (0.44.0).
6
6
  * @see https://github.com/mswjs/msw
7
7
  * - Please do NOT modify this file.
8
8
  * - Please do NOT serve this file on production.
9
9
  */
10
10
 
11
- const INTEGRITY_CHECKSUM = '02f4ad4a2797f85668baf196e553d929'
12
- const bypassHeaderName = 'x-msw-bypass'
11
+ const INTEGRITY_CHECKSUM = 'df0d85222361310ecbe1792c606e08f2'
13
12
  const activeClientIds = new Set()
14
13
 
15
14
  self.addEventListener('install', function () {
16
- return self.skipWaiting()
15
+ self.skipWaiting()
17
16
  })
18
17
 
19
- self.addEventListener('activate', async function (event) {
20
- return self.clients.claim()
18
+ self.addEventListener('activate', function (event) {
19
+ event.waitUntil(self.clients.claim())
21
20
  })
22
21
 
23
22
  self.addEventListener('message', async function (event) {
@@ -33,7 +32,9 @@ self.addEventListener('message', async function (event) {
33
32
  return
34
33
  }
35
34
 
36
- const allClients = await self.clients.matchAll()
35
+ const allClients = await self.clients.matchAll({
36
+ type: 'window',
37
+ })
37
38
 
38
39
  switch (event.data) {
39
40
  case 'KEEPALIVE_REQUEST': {
@@ -83,30 +84,58 @@ self.addEventListener('message', async function (event) {
83
84
  }
84
85
  })
85
86
 
86
- // Resolve the "main" client for the given event.
87
- // Client that issues a request doesn't necessarily equal the client
88
- // that registered the worker. It's with the latter the worker should
89
- // communicate with during the response resolving phase.
90
- async function resolveMainClient(event) {
91
- const client = await self.clients.get(event.clientId)
87
+ self.addEventListener('fetch', function (event) {
88
+ const { request } = event
89
+ const accept = request.headers.get('accept') || ''
92
90
 
93
- if (client.frameType === 'top-level') {
94
- return client
91
+ // Bypass server-sent events.
92
+ if (accept.includes('text/event-stream')) {
93
+ return
95
94
  }
96
95
 
97
- const allClients = await self.clients.matchAll()
96
+ // Bypass navigation requests.
97
+ if (request.mode === 'navigate') {
98
+ return
99
+ }
98
100
 
99
- return allClients
100
- .filter((client) => {
101
- // Get only those clients that are currently visible.
102
- return client.visibilityState === 'visible'
103
- })
104
- .find((client) => {
105
- // Find the client ID that's recorded in the
106
- // set of clients that have registered the worker.
107
- return activeClientIds.has(client.id)
108
- })
109
- }
101
+ // Opening the DevTools triggers the "only-if-cached" request
102
+ // that cannot be handled by the worker. Bypass such requests.
103
+ if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {
104
+ return
105
+ }
106
+
107
+ // Bypass all requests when there are no active clients.
108
+ // Prevents the self-unregistered worked from handling requests
109
+ // after it's been deleted (still remains active until the next reload).
110
+ if (activeClientIds.size === 0) {
111
+ return
112
+ }
113
+
114
+ // Generate unique request ID.
115
+ const requestId = Math.random().toString(16).slice(2)
116
+
117
+ event.respondWith(
118
+ handleRequest(event, requestId).catch((error) => {
119
+ if (error.name === 'NetworkError') {
120
+ console.warn(
121
+ '[MSW] Successfully emulated a network error for the "%s %s" request.',
122
+ request.method,
123
+ request.url,
124
+ )
125
+ return
126
+ }
127
+
128
+ // At this point, any exception indicates an issue with the original request/response.
129
+ console.error(
130
+ `\
131
+ [MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`,
132
+ request.method,
133
+ request.url,
134
+ `${error.name}: ${error.message}`,
135
+ )
136
+ }),
137
+ )
138
+ })
110
139
 
111
140
  async function handleRequest(event, requestId) {
112
141
  const client = await resolveMainClient(event)
@@ -128,7 +157,7 @@ async function handleRequest(event, requestId) {
128
157
  statusText: clonedResponse.statusText,
129
158
  body:
130
159
  clonedResponse.body === null ? null : await clonedResponse.text(),
131
- headers: serializeHeaders(clonedResponse.headers),
160
+ headers: Object.fromEntries(clonedResponse.headers.entries()),
132
161
  redirected: clonedResponse.redirected,
133
162
  },
134
163
  })
@@ -138,14 +167,54 @@ async function handleRequest(event, requestId) {
138
167
  return response
139
168
  }
140
169
 
170
+ // Resolve the main client for the given event.
171
+ // Client that issues a request doesn't necessarily equal the client
172
+ // that registered the worker. It's with the latter the worker should
173
+ // communicate with during the response resolving phase.
174
+ async function resolveMainClient(event) {
175
+ const client = await self.clients.get(event.clientId)
176
+
177
+ if (client.frameType === 'top-level') {
178
+ return client
179
+ }
180
+
181
+ const allClients = await self.clients.matchAll({
182
+ type: 'window',
183
+ })
184
+
185
+ return allClients
186
+ .filter((client) => {
187
+ // Get only those clients that are currently visible.
188
+ return client.visibilityState === 'visible'
189
+ })
190
+ .find((client) => {
191
+ // Find the client ID that's recorded in the
192
+ // set of clients that have registered the worker.
193
+ return activeClientIds.has(client.id)
194
+ })
195
+ }
196
+
141
197
  async function getResponse(event, client, requestId) {
142
198
  const { request } = event
143
- const requestClone = request.clone()
144
- const getOriginalResponse = () => fetch(requestClone)
199
+ const clonedRequest = request.clone()
200
+
201
+ function passthrough() {
202
+ // Clone the request because it might've been already used
203
+ // (i.e. its body has been read and sent to the cilent).
204
+ const headers = Object.fromEntries(clonedRequest.headers.entries())
145
205
 
146
- // Bypass mocking when the request client is not active.
206
+ // Remove MSW-specific request headers so the bypassed requests
207
+ // comply with the server's CORS preflight check.
208
+ // Operate with the headers as an object because request "Headers"
209
+ // are immutable.
210
+ delete headers['x-msw-bypass']
211
+
212
+ return fetch(clonedRequest, { headers })
213
+ }
214
+
215
+ // Bypass mocking when the client is not active.
147
216
  if (!client) {
148
- return getOriginalResponse()
217
+ return passthrough()
149
218
  }
150
219
 
151
220
  // Bypass initial page load requests (i.e. static assets).
@@ -153,34 +222,30 @@ async function getResponse(event, client, requestId) {
153
222
  // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
154
223
  // and is not ready to handle requests.
155
224
  if (!activeClientIds.has(client.id)) {
156
- return await getOriginalResponse()
225
+ return passthrough()
157
226
  }
158
227
 
159
- // Bypass requests with the explicit bypass header
160
- if (requestClone.headers.get(bypassHeaderName) === 'true') {
161
- const cleanRequestHeaders = serializeHeaders(requestClone.headers)
162
-
163
- // Remove the bypass header to comply with the CORS preflight check.
164
- delete cleanRequestHeaders[bypassHeaderName]
165
-
166
- const originalRequest = new Request(requestClone, {
167
- headers: new Headers(cleanRequestHeaders),
168
- })
169
-
170
- return fetch(originalRequest)
228
+ // Bypass requests with the explicit bypass header.
229
+ // Such requests can be issued by "ctx.fetch()".
230
+ if (request.headers.get('x-msw-bypass') === 'true') {
231
+ return passthrough()
171
232
  }
172
233
 
173
- // Send the request to the client-side MSW.
174
- const reqHeaders = serializeHeaders(request.headers)
175
- const body = await request.text()
234
+ // Create a communication channel scoped to the current request.
235
+ // This way events can be exchanged outside of the worker's global
236
+ // "message" event listener (i.e. abstracted into functions).
237
+ const operationChannel = new BroadcastChannel(
238
+ `msw-response-stream-${requestId}`,
239
+ )
176
240
 
241
+ // Notify the client that a request has been intercepted.
177
242
  const clientMessage = await sendToClient(client, {
178
243
  type: 'REQUEST',
179
244
  payload: {
180
245
  id: requestId,
181
246
  url: request.url,
182
247
  method: request.method,
183
- headers: reqHeaders,
248
+ headers: Object.fromEntries(request.headers.entries()),
184
249
  cache: request.cache,
185
250
  mode: request.mode,
186
251
  credentials: request.credentials,
@@ -189,22 +254,23 @@ async function getResponse(event, client, requestId) {
189
254
  redirect: request.redirect,
190
255
  referrer: request.referrer,
191
256
  referrerPolicy: request.referrerPolicy,
192
- body,
257
+ body: await request.text(),
193
258
  bodyUsed: request.bodyUsed,
194
259
  keepalive: request.keepalive,
195
260
  },
196
261
  })
197
262
 
198
263
  switch (clientMessage.type) {
199
- case 'MOCK_SUCCESS': {
200
- return delayPromise(
201
- () => respondWithMock(clientMessage),
202
- clientMessage.payload.delay,
203
- )
264
+ case 'MOCK_RESPONSE': {
265
+ return respondWithMock(clientMessage.payload)
266
+ }
267
+
268
+ case 'MOCK_RESPONSE_START': {
269
+ return respondWithMockStream(operationChannel, clientMessage.payload)
204
270
  }
205
271
 
206
272
  case 'MOCK_NOT_FOUND': {
207
- return getOriginalResponse()
273
+ return passthrough()
208
274
  }
209
275
 
210
276
  case 'NETWORK_ERROR': {
@@ -212,7 +278,7 @@ async function getResponse(event, client, requestId) {
212
278
  const networkError = new Error(message)
213
279
  networkError.name = name
214
280
 
215
- // Rejecting a request Promise emulates a network error.
281
+ // Rejecting a "respondWith" promise emulates a network error.
216
282
  throw networkError
217
283
  }
218
284
 
@@ -231,73 +297,11 @@ This exception has been gracefully handled as a 500 response, however, it's stro
231
297
  request.url,
232
298
  )
233
299
 
234
- return respondWithMock(clientMessage)
300
+ return respondWithMock(clientMessage.payload)
235
301
  }
236
302
  }
237
303
 
238
- return getOriginalResponse()
239
- }
240
-
241
- self.addEventListener('fetch', function (event) {
242
- const { request } = event
243
- const accept = request.headers.get('accept') || ''
244
-
245
- // Bypass server-sent events.
246
- if (accept.includes('text/event-stream')) {
247
- return
248
- }
249
-
250
- // Bypass navigation requests.
251
- if (request.mode === 'navigate') {
252
- return
253
- }
254
-
255
- // Opening the DevTools triggers the "only-if-cached" request
256
- // that cannot be handled by the worker. Bypass such requests.
257
- if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {
258
- return
259
- }
260
-
261
- // Bypass all requests when there are no active clients.
262
- // Prevents the self-unregistered worked from handling requests
263
- // after it's been deleted (still remains active until the next reload).
264
- if (activeClientIds.size === 0) {
265
- return
266
- }
267
-
268
- const requestId = uuidv4()
269
-
270
- return event.respondWith(
271
- handleRequest(event, requestId).catch((error) => {
272
- if (error.name === 'NetworkError') {
273
- console.warn(
274
- '[MSW] Successfully emulated a network error for the "%s %s" request.',
275
- request.method,
276
- request.url,
277
- )
278
- return
279
- }
280
-
281
- // At this point, any exception indicates an issue with the original request/response.
282
- console.error(
283
- `\
284
- [MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`,
285
- request.method,
286
- request.url,
287
- `${error.name}: ${error.message}`,
288
- )
289
- }),
290
- )
291
- })
292
-
293
- function serializeHeaders(headers) {
294
- const reqHeaders = {}
295
- headers.forEach((value, name) => {
296
- reqHeaders[name] = reqHeaders[name]
297
- ? [].concat(reqHeaders[name]).concat(value)
298
- : value
299
- })
300
- return reqHeaders
304
+ return passthrough()
301
305
  }
302
306
 
303
307
  function sendToClient(client, message) {
@@ -312,27 +316,52 @@ function sendToClient(client, message) {
312
316
  resolve(event.data)
313
317
  }
314
318
 
315
- client.postMessage(JSON.stringify(message), [channel.port2])
319
+ client.postMessage(message, [channel.port2])
316
320
  })
317
321
  }
318
322
 
319
- function delayPromise(cb, duration) {
323
+ function sleep(timeMs) {
320
324
  return new Promise((resolve) => {
321
- setTimeout(() => resolve(cb()), duration)
325
+ setTimeout(resolve, timeMs)
322
326
  })
323
327
  }
324
328
 
325
- function respondWithMock(clientMessage) {
326
- return new Response(clientMessage.payload.body, {
327
- ...clientMessage.payload,
328
- headers: clientMessage.payload.headers,
329
- })
329
+ async function respondWithMock(response) {
330
+ await sleep(response.delay)
331
+ return new Response(response.body, response)
330
332
  }
331
333
 
332
- function uuidv4() {
333
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
334
- const r = (Math.random() * 16) | 0
335
- const v = c == 'x' ? r : (r & 0x3) | 0x8
336
- return v.toString(16)
334
+ function respondWithMockStream(operationChannel, mockResponse) {
335
+ let streamCtrl
336
+ const stream = new ReadableStream({
337
+ start: (controller) => (streamCtrl = controller),
338
+ })
339
+
340
+ return new Promise(async (resolve, reject) => {
341
+ operationChannel.onmessageerror = (event) => {
342
+ operationChannel.close()
343
+ return reject(event.data.error)
344
+ }
345
+
346
+ operationChannel.onmessage = (event) => {
347
+ if (!event.data) {
348
+ return
349
+ }
350
+
351
+ switch (event.data.type) {
352
+ case 'MOCK_RESPONSE_CHUNK': {
353
+ streamCtrl.enqueue(event.data.payload)
354
+ break
355
+ }
356
+
357
+ case 'MOCK_RESPONSE_END': {
358
+ streamCtrl.close()
359
+ operationChannel.close()
360
+ }
361
+ }
362
+ }
363
+
364
+ await sleep(mockResponse.delay)
365
+ return resolve(new Response(stream, mockResponse))
337
366
  })
338
367
  }
@@ -1,4 +1,4 @@
1
- import { b as RequestHandler, i as RequestHandlerDefaultInfo, M as MockedRequest, c as DefaultBodyType, z as SetupServerApi } from '../glossary-58eca5a8.js';
1
+ import { b as RequestHandler, i as RequestHandlerDefaultInfo, M as MockedRequest, c as DefaultBodyType, I as SetupServerApi } from '../glossary-17949ef9.js';
2
2
  import 'type-fest';
3
3
  import '@mswjs/interceptors';
4
4
  import 'headers-polyfill';