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.
- package/README.md +10 -1
- package/lib/{glossary-58eca5a8.d.ts → glossary-17949ef9.d.ts} +49 -26
- package/lib/iife/index.js +4777 -2157
- package/lib/iife/index.js.map +1 -1
- package/lib/index.d.ts +11 -14
- package/lib/index.js +310 -265
- package/lib/index.js.map +1 -1
- package/lib/mockServiceWorker.js +163 -134
- package/lib/native/index.d.ts +1 -1
- package/lib/native/index.js +486 -459
- package/lib/native/index.mjs +476 -449
- package/lib/node/index.d.ts +2 -2
- package/lib/node/index.js +486 -459
- package/lib/node/index.js.map +1 -1
- package/lib/node/index.mjs +476 -449
- package/lib/node/index.mjs.map +1 -1
- package/package.json +3 -3
package/lib/mockServiceWorker.js
CHANGED
|
@@ -2,22 +2,21 @@
|
|
|
2
2
|
/* tslint:disable */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Mock Service Worker (0.
|
|
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 = '
|
|
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
|
-
|
|
15
|
+
self.skipWaiting()
|
|
17
16
|
})
|
|
18
17
|
|
|
19
|
-
self.addEventListener('activate',
|
|
20
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
94
|
-
|
|
91
|
+
// Bypass server-sent events.
|
|
92
|
+
if (accept.includes('text/event-stream')) {
|
|
93
|
+
return
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
|
|
96
|
+
// Bypass navigation requests.
|
|
97
|
+
if (request.mode === 'navigate') {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
98
100
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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:
|
|
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
|
|
144
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
225
|
+
return passthrough()
|
|
157
226
|
}
|
|
158
227
|
|
|
159
|
-
// Bypass requests with the explicit bypass header
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
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:
|
|
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 '
|
|
200
|
-
return
|
|
201
|
-
|
|
202
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
319
|
+
client.postMessage(message, [channel.port2])
|
|
316
320
|
})
|
|
317
321
|
}
|
|
318
322
|
|
|
319
|
-
function
|
|
323
|
+
function sleep(timeMs) {
|
|
320
324
|
return new Promise((resolve) => {
|
|
321
|
-
setTimeout(
|
|
325
|
+
setTimeout(resolve, timeMs)
|
|
322
326
|
})
|
|
323
327
|
}
|
|
324
328
|
|
|
325
|
-
function respondWithMock(
|
|
326
|
-
|
|
327
|
-
|
|
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
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
}
|
package/lib/native/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as RequestHandler, i as RequestHandlerDefaultInfo, M as MockedRequest, c as DefaultBodyType,
|
|
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';
|