mockServiceWorker.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /* eslint-disable */
  2. /* tslint:disable */
  3. /**
  4. * Mock Service Worker.
  5. * @see https://github.com/mswjs/msw
  6. * - Please do NOT modify this file.
  7. * - Please do NOT serve this file on production.
  8. */
  9. const PACKAGE_VERSION = '2.3.0-ws.rc-12'
  10. const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
  11. const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
  12. const activeClientIds = new Set()
  13. self.addEventListener('install', function () {
  14. self.skipWaiting()
  15. })
  16. self.addEventListener('activate', function (event) {
  17. event.waitUntil(self.clients.claim())
  18. })
  19. self.addEventListener('message', async function (event) {
  20. const clientId = event.source.id
  21. if (!clientId || !self.clients) {
  22. return
  23. }
  24. const client = await self.clients.get(clientId)
  25. if (!client) {
  26. return
  27. }
  28. const allClients = await self.clients.matchAll({
  29. type: 'window',
  30. })
  31. switch (event.data) {
  32. case 'KEEPALIVE_REQUEST': {
  33. sendToClient(client, {
  34. type: 'KEEPALIVE_RESPONSE',
  35. })
  36. break
  37. }
  38. case 'INTEGRITY_CHECK_REQUEST': {
  39. sendToClient(client, {
  40. type: 'INTEGRITY_CHECK_RESPONSE',
  41. payload: {
  42. packageVersion: PACKAGE_VERSION,
  43. checksum: INTEGRITY_CHECKSUM,
  44. },
  45. })
  46. break
  47. }
  48. case 'MOCK_ACTIVATE': {
  49. activeClientIds.add(clientId)
  50. sendToClient(client, {
  51. type: 'MOCKING_ENABLED',
  52. payload: true,
  53. })
  54. break
  55. }
  56. case 'MOCK_DEACTIVATE': {
  57. activeClientIds.delete(clientId)
  58. break
  59. }
  60. case 'CLIENT_CLOSED': {
  61. activeClientIds.delete(clientId)
  62. const remainingClients = allClients.filter((client) => {
  63. return client.id !== clientId
  64. })
  65. // Unregister itself when there are no more clients
  66. if (remainingClients.length === 0) {
  67. self.registration.unregister()
  68. }
  69. break
  70. }
  71. }
  72. })
  73. self.addEventListener('fetch', function (event) {
  74. const { request } = event
  75. // Bypass navigation requests.
  76. if (request.mode === 'navigate') {
  77. return
  78. }
  79. // Opening the DevTools triggers the "only-if-cached" request
  80. // that cannot be handled by the worker. Bypass such requests.
  81. if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {
  82. return
  83. }
  84. // Bypass all requests when there are no active clients.
  85. // Prevents the self-unregistered worked from handling requests
  86. // after it's been deleted (still remains active until the next reload).
  87. if (activeClientIds.size === 0) {
  88. return
  89. }
  90. // Generate unique request ID.
  91. const requestId = crypto.randomUUID()
  92. event.respondWith(handleRequest(event, requestId))
  93. })
  94. async function handleRequest(event, requestId) {
  95. const client = await resolveMainClient(event)
  96. const response = await getResponse(event, client, requestId)
  97. // Send back the response clone for the "response:*" life-cycle events.
  98. // Ensure MSW is active and ready to handle the message, otherwise
  99. // this message will pend indefinitely.
  100. if (client && activeClientIds.has(client.id)) {
  101. ;(async function () {
  102. const responseClone = response.clone()
  103. sendToClient(
  104. client,
  105. {
  106. type: 'RESPONSE',
  107. payload: {
  108. requestId,
  109. isMockedResponse: IS_MOCKED_RESPONSE in response,
  110. type: responseClone.type,
  111. status: responseClone.status,
  112. statusText: responseClone.statusText,
  113. body: responseClone.body,
  114. headers: Object.fromEntries(responseClone.headers.entries()),
  115. },
  116. },
  117. [responseClone.body],
  118. )
  119. })()
  120. }
  121. return response
  122. }
  123. // Resolve the main client for the given event.
  124. // Client that issues a request doesn't necessarily equal the client
  125. // that registered the worker. It's with the latter the worker should
  126. // communicate with during the response resolving phase.
  127. async function resolveMainClient(event) {
  128. const client = await self.clients.get(event.clientId)
  129. if (client?.frameType === 'top-level') {
  130. return client
  131. }
  132. const allClients = await self.clients.matchAll({
  133. type: 'window',
  134. })
  135. return allClients
  136. .filter((client) => {
  137. // Get only those clients that are currently visible.
  138. return client.visibilityState === 'visible'
  139. })
  140. .find((client) => {
  141. // Find the client ID that's recorded in the
  142. // set of clients that have registered the worker.
  143. return activeClientIds.has(client.id)
  144. })
  145. }
  146. async function getResponse(event, client, requestId) {
  147. const { request } = event
  148. // Clone the request because it might've been already used
  149. // (i.e. its body has been read and sent to the client).
  150. const requestClone = request.clone()
  151. function passthrough() {
  152. const headers = Object.fromEntries(requestClone.headers.entries())
  153. // Remove internal MSW request header so the passthrough request
  154. // complies with any potential CORS preflight checks on the server.
  155. // Some servers forbid unknown request headers.
  156. delete headers['x-msw-intention']
  157. return fetch(requestClone, { headers })
  158. }
  159. // Bypass mocking when the client is not active.
  160. if (!client) {
  161. return passthrough()
  162. }
  163. // Bypass initial page load requests (i.e. static assets).
  164. // The absence of the immediate/parent client in the map of the active clients
  165. // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
  166. // and is not ready to handle requests.
  167. if (!activeClientIds.has(client.id)) {
  168. return passthrough()
  169. }
  170. // Notify the client that a request has been intercepted.
  171. const requestBuffer = await request.arrayBuffer()
  172. const clientMessage = await sendToClient(
  173. client,
  174. {
  175. type: 'REQUEST',
  176. payload: {
  177. id: requestId,
  178. url: request.url,
  179. mode: request.mode,
  180. method: request.method,
  181. headers: Object.fromEntries(request.headers.entries()),
  182. cache: request.cache,
  183. credentials: request.credentials,
  184. destination: request.destination,
  185. integrity: request.integrity,
  186. redirect: request.redirect,
  187. referrer: request.referrer,
  188. referrerPolicy: request.referrerPolicy,
  189. body: requestBuffer,
  190. keepalive: request.keepalive,
  191. },
  192. },
  193. [requestBuffer],
  194. )
  195. switch (clientMessage.type) {
  196. case 'MOCK_RESPONSE': {
  197. return respondWithMock(clientMessage.data)
  198. }
  199. case 'PASSTHROUGH': {
  200. return passthrough()
  201. }
  202. }
  203. return passthrough()
  204. }
  205. function sendToClient(client, message, transferrables = []) {
  206. return new Promise((resolve, reject) => {
  207. const channel = new MessageChannel()
  208. channel.port1.onmessage = (event) => {
  209. if (event.data && event.data.error) {
  210. return reject(event.data.error)
  211. }
  212. resolve(event.data)
  213. }
  214. client.postMessage(
  215. message,
  216. [channel.port2].concat(transferrables.filter(Boolean)),
  217. )
  218. })
  219. }
  220. async function respondWithMock(response) {
  221. // Setting response status code to 0 is a no-op.
  222. // However, when responding with a "Response.error()", the produced Response
  223. // instance will have status code set to 0. Since it's not possible to create
  224. // a Response instance with status code 0, handle that use-case separately.
  225. if (response.status === 0) {
  226. return Response.error()
  227. }
  228. const mockedResponse = new Response(response.body, response)
  229. Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
  230. value: true,
  231. enumerable: true,
  232. })
  233. return mockedResponse
  234. }