mockServiceWorker.js (8133B)
1 /* eslint-disable */ 2 /* tslint:disable */ 3 4 /** 5 * Mock Service Worker (1.3.1). 6 * @see https://github.com/mswjs/msw 7 * - Please do NOT modify this file. 8 * - Please do NOT serve this file on production. 9 */ 10 11 const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70' 12 const activeClientIds = new Set() 13 14 self.addEventListener('install', function () { 15 self.skipWaiting() 16 }) 17 18 self.addEventListener('activate', function (event) { 19 event.waitUntil(self.clients.claim()) 20 }) 21 22 self.addEventListener('message', async function (event) { 23 const clientId = event.source.id 24 25 if (!clientId || !self.clients) { 26 return 27 } 28 29 const client = await self.clients.get(clientId) 30 31 if (!client) { 32 return 33 } 34 35 const allClients = await self.clients.matchAll({ 36 type: 'window', 37 }) 38 39 switch (event.data) { 40 case 'KEEPALIVE_REQUEST': { 41 sendToClient(client, { 42 type: 'KEEPALIVE_RESPONSE', 43 }) 44 break 45 } 46 47 case 'INTEGRITY_CHECK_REQUEST': { 48 sendToClient(client, { 49 type: 'INTEGRITY_CHECK_RESPONSE', 50 payload: INTEGRITY_CHECKSUM, 51 }) 52 break 53 } 54 55 case 'MOCK_ACTIVATE': { 56 activeClientIds.add(clientId) 57 58 sendToClient(client, { 59 type: 'MOCKING_ENABLED', 60 payload: true, 61 }) 62 break 63 } 64 65 case 'MOCK_DEACTIVATE': { 66 activeClientIds.delete(clientId) 67 break 68 } 69 70 case 'CLIENT_CLOSED': { 71 activeClientIds.delete(clientId) 72 73 const remainingClients = allClients.filter((client) => { 74 return client.id !== clientId 75 }) 76 77 // Unregister itself when there are no more clients 78 if (remainingClients.length === 0) { 79 self.registration.unregister() 80 } 81 82 break 83 } 84 } 85 }) 86 87 self.addEventListener('fetch', function (event) { 88 const { request } = event 89 const accept = request.headers.get('accept') || '' 90 91 // Bypass server-sent events. 92 if (accept.includes('text/event-stream')) { 93 return 94 } 95 96 // Bypass navigation requests. 97 if (request.mode === 'navigate') { 98 return 99 } 100 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 }) 139 140 async function handleRequest(event, requestId) { 141 const client = await resolveMainClient(event) 142 const response = await getResponse(event, client, requestId) 143 144 // Send back the response clone for the "response:*" life-cycle events. 145 // Ensure MSW is active and ready to handle the message, otherwise 146 // this message will pend indefinitely. 147 if (client && activeClientIds.has(client.id)) { 148 ;(async function () { 149 const clonedResponse = response.clone() 150 sendToClient(client, { 151 type: 'RESPONSE', 152 payload: { 153 requestId, 154 type: clonedResponse.type, 155 ok: clonedResponse.ok, 156 status: clonedResponse.status, 157 statusText: clonedResponse.statusText, 158 body: 159 clonedResponse.body === null ? null : await clonedResponse.text(), 160 headers: Object.fromEntries(clonedResponse.headers.entries()), 161 redirected: clonedResponse.redirected, 162 }, 163 }) 164 })() 165 } 166 167 return response 168 } 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 197 async function getResponse(event, client, requestId) { 198 const { request } = event 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 client). 204 const headers = Object.fromEntries(clonedRequest.headers.entries()) 205 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. 216 if (!client) { 217 return passthrough() 218 } 219 220 // Bypass initial page load requests (i.e. static assets). 221 // The absence of the immediate/parent client in the map of the active clients 222 // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet 223 // and is not ready to handle requests. 224 if (!activeClientIds.has(client.id)) { 225 return passthrough() 226 } 227 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() 232 } 233 234 // Notify the client that a request has been intercepted. 235 const clientMessage = await sendToClient(client, { 236 type: 'REQUEST', 237 payload: { 238 id: requestId, 239 url: request.url, 240 method: request.method, 241 headers: Object.fromEntries(request.headers.entries()), 242 cache: request.cache, 243 mode: request.mode, 244 credentials: request.credentials, 245 destination: request.destination, 246 integrity: request.integrity, 247 redirect: request.redirect, 248 referrer: request.referrer, 249 referrerPolicy: request.referrerPolicy, 250 body: await request.text(), 251 bodyUsed: request.bodyUsed, 252 keepalive: request.keepalive, 253 }, 254 }) 255 256 switch (clientMessage.type) { 257 case 'MOCK_RESPONSE': { 258 return respondWithMock(clientMessage.data) 259 } 260 261 case 'MOCK_NOT_FOUND': { 262 return passthrough() 263 } 264 265 case 'NETWORK_ERROR': { 266 const { name, message } = clientMessage.data 267 const networkError = new Error(message) 268 networkError.name = name 269 270 // Rejecting a "respondWith" promise emulates a network error. 271 throw networkError 272 } 273 } 274 275 return passthrough() 276 } 277 278 function sendToClient(client, message) { 279 return new Promise((resolve, reject) => { 280 const channel = new MessageChannel() 281 282 channel.port1.onmessage = (event) => { 283 if (event.data && event.data.error) { 284 return reject(event.data.error) 285 } 286 287 resolve(event.data) 288 } 289 290 client.postMessage(message, [channel.port2]) 291 }) 292 } 293 294 function sleep(timeMs) { 295 return new Promise((resolve) => { 296 setTimeout(resolve, timeMs) 297 }) 298 } 299 300 async function respondWithMock(response) { 301 await sleep(response.delay) 302 return new Response(response.body, response) 303 }