@depup/msw 3.0.1-depup.0 → 3.0.3-depup.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.
Files changed (39) hide show
  1. package/README.md +5 -4
  2. package/changes.json +7 -3
  3. package/lib/_chunks/cookie-store.js +3 -2
  4. package/lib/_chunks/cookie-store.js.map +1 -1
  5. package/lib/_chunks/interceptor-source.d.ts +5 -1
  6. package/lib/_chunks/interceptor-source.js +18 -5
  7. package/lib/_chunks/interceptor-source.js.map +1 -1
  8. package/lib/_chunks/request-handler.d.ts +3 -2
  9. package/lib/browser/index.d.ts +4 -9
  10. package/lib/browser/index.js +21 -14
  11. package/lib/browser/index.js.map +1 -1
  12. package/lib/graphql/index.d.ts +19 -4
  13. package/lib/graphql/index.js +24 -12
  14. package/lib/graphql/index.js.map +1 -1
  15. package/lib/iife/index.js +66 -33
  16. package/lib/iife/index.js.map +1 -1
  17. package/lib/mockServiceWorker.js +1 -1
  18. package/lib/vite/index.js +10 -7
  19. package/lib/vite/index.js.map +1 -1
  20. package/lib/vite/runtime.d.ts +2 -3
  21. package/lib/vite/runtime.js +70 -68
  22. package/lib/vite/runtime.js.map +1 -1
  23. package/package.json +12 -9
  24. package/src/browser/default-network-options.ts +1 -1
  25. package/src/browser/setup-worker.ts +1 -4
  26. package/src/browser/sources/fallback-http-source.ts +11 -8
  27. package/src/browser/sources/service-worker-source.ts +12 -5
  28. package/src/browser/utils/should-invalidate-worker.test.ts +0 -16
  29. package/src/core/experimental/define-network.ts +1 -1
  30. package/src/core/experimental/handlers-controller.test.ts +61 -0
  31. package/src/core/experimental/handlers-controller.ts +39 -6
  32. package/src/core/experimental/sources/network-source.ts +8 -1
  33. package/src/core/handlers/handler.ts +3 -2
  34. package/src/graphql/graphql-subscription.ts +30 -12
  35. package/src/vite/plugin.test.ts +1 -1
  36. package/src/vite/plugin.ts +13 -10
  37. package/src/vite/runtime.ts +85 -85
  38. package/src/vite/tsconfig.build.json +1 -1
  39. package/src/vite/options.d.ts +0 -5
@@ -208,6 +208,10 @@ var ServiceWorkerSource = class ServiceWorkerSource extends NetworkSource {
208
208
  }
209
209
  #options;
210
210
  /**
211
+ * The resolved context of the network this source was last enabled with.
212
+ */
213
+ #context;
214
+ /**
211
215
  * @note We cannot use `WeakMap` here as request/response
212
216
  * identity cannot be preserved through the client-worker channel.
213
217
  */
@@ -229,7 +233,8 @@ var ServiceWorkerSource = class ServiceWorkerSource extends NetworkSource {
229
233
  this.#workerState = "pending";
230
234
  this.#channel = new WorkerChannel({ getWorker: () => this.workerPromise.then(([worker]) => worker) });
231
235
  }
232
- async enable() {
236
+ async enable(context) {
237
+ this.#context = context;
233
238
  this.#channel.removeAllListeners();
234
239
  this.#frames.clear();
235
240
  this.#listenerController = new AbortController();
@@ -250,7 +255,7 @@ var ServiceWorkerSource = class ServiceWorkerSource extends NetworkSource {
250
255
  clientConfirmationPromise.resolve(event.data.client);
251
256
  });
252
257
  await clientConfirmationPromise.promise;
253
- if (!this.#options.quiet) this.#printStartMessage();
258
+ if (!this.#context?.quiet) this.#printStartMessage();
254
259
  return registration;
255
260
  }
256
261
  async disable() {
@@ -272,7 +277,7 @@ var ServiceWorkerSource = class ServiceWorkerSource extends NetworkSource {
272
277
  * worker forwards after `stop()` can be answered with `PASSTHROUGH` by
273
278
  * `#handleRequest`. `#startWorker` swaps in a fresh deferred on re-enable.
274
279
  */
275
- if (!this.#options.quiet) this.#printStopMessage();
280
+ if (!this.#context?.quiet) this.#printStopMessage();
276
281
  }
277
282
  /**
278
283
  * Terminal teardown. Unregisters the Service Worker, tears down the channel,
@@ -339,7 +344,7 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
339
344
  this.#keepAliveInterval = window.setInterval(() => {
340
345
  this.#channel.postMessage("KEEPALIVE_REQUEST");
341
346
  }, 5e3);
342
- if (!this.#options.quiet) validateWorkerScope(registration);
347
+ if (!this.#context?.quiet) validateWorkerScope(registration);
343
348
  return [worker, registration];
344
349
  }
345
350
  async #handleRequest(event) {
@@ -495,18 +500,21 @@ var ServiceWorkerHttpNetworkFrame = class extends HttpNetworkFrame {
495
500
  //#endregion
496
501
  //#region src/browser/sources/fallback-http-source.ts
497
502
  var FallbackHttpSource = class extends InterceptorSource {
498
- options;
499
- constructor(options) {
503
+ /**
504
+ * The resolved context of the network this source was last enabled with.
505
+ */
506
+ #context;
507
+ constructor() {
500
508
  super({ interceptors: [new XMLHttpRequestInterceptor(), new FetchInterceptor()] });
501
- this.options = options;
502
509
  }
503
- enable() {
510
+ enable(context) {
511
+ this.#context = context;
504
512
  super.enable();
505
- if (!this.options.quiet) this.#printStartMessage();
513
+ if (!this.#context?.quiet) this.#printStartMessage();
506
514
  }
507
515
  disable() {
508
516
  super.disable();
509
- if (!this.options.quiet) this.#printStopMessage();
517
+ if (!this.#context?.quiet) this.#printStopMessage();
510
518
  }
511
519
  #printStartMessage() {
512
520
  console.groupCollapsed(`%c${devUtils.formatMessage("Mocking enabled (fallback mode).")}`, "color:orangered;font-weight:bold;");
@@ -544,9 +552,8 @@ function setupWorker(...handlers) {
544
552
  url: options?.serviceWorker?.url?.toString() || DEFAULT_WORKER_URL,
545
553
  options: options?.serviceWorker?.options
546
554
  },
547
- findWorker: options?.findWorker,
548
- quiet: options?.quiet
549
- }) : new FallbackHttpSource({ quiet: options?.quiet });
555
+ findWorker: options?.findWorker
556
+ }) : new FallbackHttpSource();
550
557
  network.configure({
551
558
  sources: [httpSource, new InterceptorSource({ interceptors: [new WebSocketInterceptor()] })],
552
559
  onUnhandledFrame: options?.onUnhandledFrame ?? "warn",
@@ -573,7 +580,7 @@ function setupWorker(...handlers) {
573
580
  //#region src/browser/default-network-options.ts
574
581
  function createDefaultNetworkOptions(workerUrl = "/mockServiceWorker.js") {
575
582
  return {
576
- sources: [supportsServiceWorker() ? new ServiceWorkerSource({ serviceWorker: { url: workerUrl } }) : new FallbackHttpSource({}), new InterceptorSource({ interceptors: [new WebSocketInterceptor()] })],
583
+ sources: [supportsServiceWorker() ? new ServiceWorkerSource({ serviceWorker: { url: workerUrl } }) : new FallbackHttpSource(), new InterceptorSource({ interceptors: [new WebSocketInterceptor()] })],
577
584
  onUnhandledFrame: "warn"
578
585
  };
579
586
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/browser/utils/supports.ts","../../src/core/utils/to-response-init.ts","../../src/browser/utils/get-absolute-worker-url.ts","../../src/browser/utils/get-worker-by-registration.ts","../../src/browser/utils/get-worker-instance.ts","../../src/browser/utils/worker-channel.ts","../../src/browser/utils/deserialize-request.ts","../../src/browser/utils/validate-worker-scope.ts","../../src/browser/utils/should-invalidate-worker.ts","../../src/browser/sources/service-worker-source.ts","../../src/browser/sources/fallback-http-source.ts","../../src/browser/setup-worker.ts","../../src/browser/default-network-options.ts"],"sourcesContent":["/**\n * Checks if the Service Worker API is supproted and available\n * in the current browsing context.\n */\nexport function supportsServiceWorker(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n 'serviceWorker' in navigator &&\n typeof location !== 'undefined' &&\n location.protocol !== 'file:'\n )\n}\n\n/**\n * Returns a boolean indicating whether the current browser\n * supports `ReadableStream` as a `Transferable` when posting\n * messages.\n */\nexport function supportsReadableStreamTransfer() {\n try {\n const stream = new ReadableStream({\n start: (controller) => controller.close(),\n })\n const message = new MessageChannel()\n message.port1.postMessage(stream, [stream])\n return true\n } catch {\n return false\n }\n}\n","export function toResponseInit(response: Response): ResponseInit {\n return {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n }\n}\n","/**\n * Returns an absolute Service Worker URL based on the given\n * relative URL (known during the registration).\n */\nexport function getAbsoluteWorkerUrl(workerUrl: string): string {\n return new URL(workerUrl, location.href).href\n}\n","import type { FindWorker } from '../glossary'\n\n/**\n * Attempts to resolve a Service Worker instance from a given registration,\n * regardless of its state (active, installing, waiting).\n */\nexport function getWorkerByRegistration(\n registration: ServiceWorkerRegistration,\n absoluteWorkerUrl: string,\n findWorker: FindWorker,\n): ServiceWorker | null {\n const allStates = [\n registration.active,\n registration.installing,\n registration.waiting,\n ]\n\n const relevantStates = allStates.filter((state): state is ServiceWorker => {\n return state != null\n })\n\n const worker = relevantStates.find((worker) => {\n return findWorker(worker.scriptURL, absoluteWorkerUrl)\n })\n\n return worker || null\n}\n","import { until } from 'until-async'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport { getAbsoluteWorkerUrl } from './get-absolute-worker-url'\nimport { getWorkerByRegistration } from './get-worker-by-registration'\nimport type { ServiceWorkerInstanceTuple, FindWorker } from '../glossary'\n\n/**\n * Returns an active Service Worker instance.\n * When not found, registers a new Service Worker.\n */\nexport const getWorkerInstance = async (\n url: string,\n options: RegistrationOptions = {},\n findWorker: FindWorker,\n): Promise<ServiceWorkerInstanceTuple> => {\n // Resolve the absolute Service Worker URL.\n const absoluteWorkerUrl = getAbsoluteWorkerUrl(url)\n\n const mockRegistrations = await navigator.serviceWorker\n .getRegistrations()\n .then((registrations) =>\n registrations.filter((registration) =>\n getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),\n ),\n )\n if (!navigator.serviceWorker.controller && mockRegistrations.length > 0) {\n // Reload the page when it has associated workers, but no active controller.\n // The absence of a controller can mean either:\n // - page has no Service Worker associated with it\n // - page has been hard-reloaded and its workers won't be used until the next reload.\n // Since we've checked that there are registrations associated with this page,\n // at this point we are sure it's hard reload that falls into this clause.\n location.reload()\n }\n\n const [existingRegistration] = mockRegistrations\n\n if (existingRegistration) {\n // Schedule the worker update in the background.\n // Update ensures the existing worker is up-to-date.\n existingRegistration.update()\n\n // Return the worker reference immediately.\n return [\n getWorkerByRegistration(\n existingRegistration,\n absoluteWorkerUrl,\n findWorker,\n ),\n existingRegistration,\n ]\n }\n\n // When the Service Worker wasn't found, register it anew and return the reference.\n const [registrationError, registrationResult] = await until<\n Error,\n ServiceWorkerInstanceTuple\n >(async () => {\n const registration = await navigator.serviceWorker.register(url, options)\n return [\n // Compare existing worker registration by its worker URL,\n // to prevent irrelevant workers to resolve here (such as Codesandbox worker).\n getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),\n registration,\n ]\n })\n\n // Handle Service Worker registration errors.\n if (registrationError) {\n const isWorkerMissing = registrationError.message.includes('(404)')\n\n // Produce a custom error message when given a non-existing Service Worker url.\n // Suggest developers to check their setup.\n if (isWorkerMissing) {\n const scopeUrl = new URL(options?.scope || '/', location.href)\n\n throw new Error(\n devUtils.formatMessage(`\\\nFailed to register a Service Worker for scope ('${scopeUrl.href}') with script ('${absoluteWorkerUrl}'): Service Worker script does not exist at the given path.\n\nDid you forget to run \"npx msw init <PUBLIC_DIR>\"?\n\nLearn more about creating the Service Worker script: https://mswjs.io/docs/cli/init`),\n )\n }\n\n // Fallback error message for any other registration errors.\n throw new Error(\n devUtils.formatMessage(\n 'Failed to register the Service Worker:\\n\\n%s',\n registrationError.message,\n ),\n )\n }\n\n return registrationResult\n}\n","import { invariant } from 'outvariant'\nimport { Emitter, TypedEvent } from 'rettime'\nimport { isObject } from '#core/utils/internal/is-object'\nimport type { StringifiedResponse } from '../glossary'\nimport { supportsServiceWorker } from '../utils/supports'\n\nexport type WorkerChannelEventMap = {\n REQUEST: WorkerEvent<IncomingWorkerRequest>\n RESPONSE: WorkerEvent<IncomingWorkerResponse>\n REQUEST_ERROR: WorkerEvent<IncomingWorkerRequestError>\n MOCKING_ENABLED: WorkerEvent<{\n client: {\n id: string\n frameType: string\n }\n }>\n CLIENT_CLOSED: TypedEvent<never>\n INTEGRITY_CHECK_RESPONSE: WorkerEvent<{\n packageVersion: string\n checksum: string\n }>\n KEEPALIVE_RESPONSE: TypedEvent<never>\n}\n\n/**\n * Request representation received from the worker message event.\n */\nexport interface IncomingWorkerRequest extends Omit<\n Request,\n | 'text'\n | 'body'\n | 'json'\n | 'blob'\n | 'arrayBuffer'\n | 'formData'\n | 'clone'\n | 'signal'\n | 'isHistoryNavigation'\n | 'isReloadNavigation'\n> {\n /**\n * Unique ID of the request generated once the request is\n * intercepted by the \"fetch\" event in the Service Worker.\n */\n id: string\n body?: ArrayBuffer | null\n}\n\ntype IncomingWorkerResponse = {\n isMockedResponse: boolean\n request: IncomingWorkerRequest\n response: Pick<\n Response,\n 'type' | 'ok' | 'status' | 'statusText' | 'body' | 'headers' | 'redirected'\n >\n}\n\n/**\n * Notification that a request has settled without producing a response\n * (e.g. a passthrough request failed with a network error).\n */\ntype IncomingWorkerRequestError = {\n request: Pick<IncomingWorkerRequest, 'id'>\n error: Pick<Error, 'name' | 'message'>\n}\n\n/**\n * Request modifications to apply to the passthrough request in the worker.\n */\nexport interface PassthroughPayload {\n request: {\n /**\n * Request headers as a list of entries to support\n * multiple headers with the same name.\n */\n headers: Array<[string, string]>\n }\n}\n\ntype WorkerEventResponse = {\n MOCK_RESPONSE: [\n data: StringifiedResponse,\n transfer?: [ReadableStream<Uint8Array>],\n ]\n PASSTHROUGH: [data: PassthroughPayload]\n}\n\nconst SUPPORTS_SERVICE_WORKER = supportsServiceWorker()\n\nclass WorkerEvent<\n DataType,\n ReturnType = any,\n EventType extends string = string,\n> extends TypedEvent<DataType, ReturnType, EventType> {\n #workerEvent: MessageEvent\n\n constructor(workerEvent: MessageEvent) {\n const type = workerEvent.data.type as EventType\n const data = workerEvent.data.payload as DataType\n\n /**\n * @note This is the only place we're mapping { type, payload }\n * message structure of the worker. The client references the\n * payload via `event.data`.\n */\n super(\n // @ts-expect-error Troublesome `TypedEvent` extension.\n type,\n { data },\n )\n this.#workerEvent = workerEvent\n }\n\n get ports() {\n return this.#workerEvent.ports\n }\n\n /**\n * Reply directly to this event using its `MessagePort`.\n */\n public postMessage<Type extends keyof WorkerEventResponse>(\n type: Type,\n ...rest: WorkerEventResponse[Type]\n ): void {\n this.#workerEvent.ports[0].postMessage(\n { type, data: rest[0] },\n { transfer: rest[1] },\n )\n }\n}\n\n/**\n * Map of the events that can be sent to the Service Worker\n * from any execution context.\n */\ntype OutgoingWorkerEvents =\n | 'MOCK_ACTIVATE'\n | 'INTEGRITY_CHECK_REQUEST'\n | 'KEEPALIVE_REQUEST'\n | 'CLIENT_CLOSE'\n\nexport interface WorkerChannelOptions {\n getWorker: () => Promise<ServiceWorker>\n}\n\nexport class WorkerChannel extends Emitter<WorkerChannelEventMap> {\n #getWorker: WorkerChannelOptions['getWorker']\n #controller: AbortController\n\n constructor(options: WorkerChannelOptions) {\n super()\n\n invariant(\n SUPPORTS_SERVICE_WORKER,\n 'Failed to open a WorkerChannel: Service Worker is not supported in this environment.',\n )\n\n this.#getWorker = options.getWorker\n this.#controller = new AbortController()\n\n navigator.serviceWorker.addEventListener(\n 'message',\n async (event) => {\n const worker = await this.#getWorker()\n\n if (event.source != null && event.source !== worker) {\n return\n }\n\n if (event.data && isObject(event.data) && 'type' in event.data) {\n this.emit(new WorkerEvent<any, any, any>(event))\n }\n },\n {\n signal: this.#controller.signal,\n },\n )\n }\n\n /**\n * Send data to the Service Worker controlling this client.\n * This triggers the `message` event listener on ServiceWorkerGlobalScope.\n */\n public postMessage(type: OutgoingWorkerEvents): void {\n invariant(\n SUPPORTS_SERVICE_WORKER,\n 'Failed to post message on a WorkerChannel: the Service Worker API is unavailable in this environment. This is likely an issue with MSW. Please report it on GitHub: https://github.com/mswjs/msw/issues',\n )\n\n this.#getWorker().then((worker) => {\n worker.postMessage(type)\n })\n }\n\n /**\n * Terminal teardown. Removes the `navigator.serviceWorker` message listener\n * and all emitter subscriptions. The channel is not usable afterwards.\n */\n public terminate(): void {\n this.#controller.abort()\n this.removeAllListeners()\n }\n}\n","import { FetchRequest } from '@mswjs/interceptors'\nimport type { IncomingWorkerRequest } from './worker-channel'\n\n/**\n * Converts a given request received from the Service Worker\n * into a Fetch `Request` instance.\n */\nexport function deserializeRequest(\n serializedRequest: IncomingWorkerRequest,\n): Request {\n return new FetchRequest(serializedRequest.url, {\n ...serializedRequest,\n })\n}\n","import { devUtils } from '#core/utils/internal/dev-utils'\n\n/**\n * Print a warning if the given Service Worker registration has a scope\n * outside of the current page's location. That is to help with debugging\n * issues caused by the incorrectly registered Service Worker.\n */\nexport function validateWorkerScope(\n registration: ServiceWorkerRegistration,\n): void {\n if (!location.href.startsWith(registration.scope)) {\n devUtils.warn(\n `Cannot intercept requests on this page because it's outside of the worker's scope (\"${registration.scope}\"). If you wish to mock API requests on this page, you must resolve this scope issue.\n\n- (Recommended) Register the worker at the root level (\"/\") of your application.\n- Set the \"Service-Worker-Allowed\" response header to allow out-of-scope workers.`,\n )\n }\n}\n","import type { ServiceWorkerSourceOptions } from '../sources/service-worker-source'\n\nexport function shouldInvalidateWorker(\n prevOptions: ServiceWorkerSourceOptions,\n nextOptions: ServiceWorkerSourceOptions,\n): boolean {\n return (\n prevOptions.findWorker !== nextOptions.findWorker ||\n prevOptions.serviceWorker.url !== nextOptions.serviceWorker.url ||\n JSON.stringify(prevOptions.serviceWorker.options) !==\n JSON.stringify(nextOptions.serviceWorker.options)\n )\n}\n","import { invariant } from 'outvariant'\nimport type { Emitter } from 'rettime'\nimport { FetchResponse } from '@mswjs/interceptors'\nimport { NetworkSource } from '#core/experimental/sources/network-source'\nimport { RequestHandler } from '#core/handlers/request-handler'\nimport {\n HttpNetworkFrame,\n ResponseEvent,\n} from '#core/experimental/frames/http-frame'\nimport { HttpResponse } from '#http/http-response'\nimport { toResponseInit } from '#core/utils/to-response-init'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport {\n supportsReadableStreamTransfer,\n supportsServiceWorker,\n} from '../utils/supports'\nimport { getWorkerInstance } from '../utils/get-worker-instance'\nimport type { WorkerChannelEventMap } from '../utils/worker-channel'\nimport { WorkerChannel } from '../utils/worker-channel'\nimport type { FindWorker } from '../glossary'\nimport { deserializeRequest } from '../utils/deserialize-request'\nimport { validateWorkerScope } from '../utils/validate-worker-scope'\nimport { shouldInvalidateWorker } from '../utils/should-invalidate-worker'\n\nexport interface ServiceWorkerSourceOptions {\n quiet?: boolean\n serviceWorker: {\n url: string\n options?: RegistrationOptions\n }\n findWorker?: FindWorker\n}\n\ntype WorkerChannelRequestEvent = Emitter.Event<\n WorkerChannel,\n 'REQUEST',\n WorkerChannelEventMap\n>\n\ntype WorkerChannelResponseEvent = Emitter.Event<\n WorkerChannel,\n 'RESPONSE',\n WorkerChannelEventMap\n>\n\ntype WorkerChannelRequestErrorEvent = Emitter.Event<\n WorkerChannel,\n 'REQUEST_ERROR',\n WorkerChannelEventMap\n>\n\ntype WorkerChannelClient =\n WorkerChannelEventMap['MOCKING_ENABLED']['data']['client']\n\nexport class ServiceWorkerSource extends NetworkSource<ServiceWorkerHttpNetworkFrame> {\n static #current?: ServiceWorkerSource\n\n /**\n * Create a new Service Worker source or reuse an existing one.\n * These sources act as a singleton and only get recreated if the options change.\n */\n public static async from(\n options: ServiceWorkerSourceOptions,\n ): Promise<ServiceWorkerSource> {\n if (ServiceWorkerSource.#current == null) {\n ServiceWorkerSource.#current = new ServiceWorkerSource(options)\n } else if (\n shouldInvalidateWorker(ServiceWorkerSource.#current.#options, options)\n ) {\n await ServiceWorkerSource.#current.terminate()\n ServiceWorkerSource.#current = new ServiceWorkerSource(options)\n }\n\n return ServiceWorkerSource.#current\n }\n\n #options: ServiceWorkerSourceOptions\n /**\n * @note We cannot use `WeakMap` here as request/response\n * identity cannot be preserved through the client-worker channel.\n */\n #frames: Map<string, ServiceWorkerHttpNetworkFrame>\n #channel: WorkerChannel\n #listenerController?: AbortController\n #clientPromise?: Promise<WorkerChannelClient>\n #keepAliveInterval?: number\n\n public workerPromise: Promise<[ServiceWorker, ServiceWorkerRegistration]>\n #workerResolvers: PromiseWithResolvers<\n [ServiceWorker, ServiceWorkerRegistration]\n >\n #workerState: 'pending' | 'fulfilled' | 'rejected'\n\n constructor(options: ServiceWorkerSourceOptions) {\n super()\n\n invariant(\n supportsServiceWorker(),\n 'Failed to use Service Worker as the network source: the Service Worker API is not supported in this environment',\n )\n\n this.#options = options\n this.#frames = new Map()\n this.#workerResolvers = Promise.withResolvers()\n this.workerPromise = this.#workerResolvers.promise\n this.#workerState = 'pending'\n this.#channel = new WorkerChannel({\n getWorker: () => this.workerPromise.then(([worker]) => worker),\n })\n }\n\n public async enable(): Promise<ServiceWorkerRegistration> {\n this.#channel.removeAllListeners()\n this.#frames.clear()\n\n this.#listenerController = new AbortController()\n const [worker, registration] = await this.#startWorker()\n\n if (worker.state !== 'activated') {\n const controller = new AbortController()\n const activationPromise = Promise.withResolvers<void>()\n activationPromise.promise.then(() => controller.abort())\n\n worker.addEventListener(\n 'statechange',\n () => {\n if (worker.state === 'activated') {\n activationPromise.resolve()\n }\n },\n {\n signal: controller.signal,\n },\n )\n\n await activationPromise.promise\n }\n\n this.#channel.postMessage('MOCK_ACTIVATE')\n\n const clientConfirmationPromise =\n Promise.withResolvers<WorkerChannelClient>()\n this.#clientPromise = clientConfirmationPromise.promise\n\n this.#channel.once('MOCKING_ENABLED', (event) => {\n clientConfirmationPromise.resolve(event.data.client)\n })\n await clientConfirmationPromise.promise\n\n if (!this.#options.quiet) {\n this.#printStartMessage()\n }\n\n return registration\n }\n\n public async disable(): Promise<void> {\n /**\n * @note Do NOT call `super.disable()` because it removes any \"frame\" listeners\n * from this network source, effectively turning it off. The Service Worker source\n * is a bit special since it might process in-flight requests that have been performed\n * after it's been disabled.\n */\n\n this.#listenerController?.abort()\n this.#listenerController = undefined\n\n const closedPromise = Promise.withResolvers<void>()\n this.#channel.once('CLIENT_CLOSED', () => closedPromise.resolve())\n\n this.#channel.postMessage('CLIENT_CLOSE')\n await closedPromise.promise\n\n /**\n * @note Do NOT reset `workerPromise` here. The channel must continue to\n * resolve the currently registered SW so that any in-flight requests the\n * worker forwards after `stop()` can be answered with `PASSTHROUGH` by\n * `#handleRequest`. `#startWorker` swaps in a fresh deferred on re-enable.\n */\n\n if (!this.#options.quiet) {\n this.#printStopMessage()\n }\n }\n\n /**\n * Terminal teardown. Unregisters the Service Worker, tears down the channel,\n * and clears timers. Called when the singleton is being replaced with one\n * that has different options. The instance is not usable afterwards.\n */\n public async terminate(): Promise<void> {\n if (this.#keepAliveInterval != null) {\n clearInterval(this.#keepAliveInterval)\n this.#keepAliveInterval = undefined\n }\n\n this.#frames.clear()\n this.#channel.terminate()\n this.#listenerController?.abort()\n this.#listenerController = undefined\n\n if (this.#workerState === 'fulfilled') {\n const [, registration] = await this.workerPromise\n await registration.unregister()\n }\n\n if (ServiceWorkerSource.#current === this) {\n ServiceWorkerSource.#current = undefined\n }\n }\n\n async #startWorker() {\n if (this.#keepAliveInterval) {\n clearInterval(this.#keepAliveInterval)\n }\n\n const workerUrl = this.#options.serviceWorker.url\n\n const [worker, registration] = await getWorkerInstance(\n workerUrl,\n this.#options.serviceWorker.options,\n this.#options.findWorker || this.#defaultFindWorker,\n )\n\n if (worker == null) {\n const missingWorkerMessage = this.#options?.findWorker\n ? devUtils.formatMessage(\n `Failed to locate the Service Worker registration using a custom \"findWorker\" predicate.\n\nPlease ensure that the custom predicate properly locates the Service Worker registration at \"%s\".\nMore details: https://mswjs.io/docs/api/setup-worker/start#findworker\n `,\n workerUrl,\n )\n : devUtils.formatMessage(\n `Failed to locate the Service Worker registration.\n\nThis most likely means that the worker script URL \"%s\" cannot resolve against the actual public hostname (%s). This may happen if your application runs behind a proxy, or has a dynamic hostname.\n\nPlease consider using a custom \"serviceWorker.url\" option to point to the actual worker script location, or a custom \"findWorker\" option to resolve the Service Worker registration manually. More details: https://mswjs.io/docs/api/setup-worker/start`,\n workerUrl,\n location.host,\n )\n\n throw new Error(missingWorkerMessage)\n }\n\n if (this.#workerState === 'pending') {\n this.#workerResolvers.resolve([worker, registration])\n this.#workerState = 'fulfilled'\n } else {\n /**\n * @note Re-enable after `stop()`: the previous `workerPromise` is already\n * fulfilled and cannot be resolved again. Swap in a pre-resolved one so\n * `getWorker()` sees the new worker instance immediately.\n */\n this.#workerResolvers = Promise.withResolvers()\n this.#workerResolvers.resolve([worker, registration])\n this.workerPromise = this.#workerResolvers.promise\n }\n\n this.#channel.on('REQUEST', this.#handleRequest.bind(this))\n this.#channel.on('RESPONSE', this.#handleResponse.bind(this))\n this.#channel.on('REQUEST_ERROR', this.#handleRequestError.bind(this))\n\n window.addEventListener(\n 'pagehide',\n (event) => {\n if (event.persisted) {\n return\n }\n\n if (worker.state !== 'redundant') {\n this.#channel.postMessage('CLIENT_CLOSE')\n }\n\n clearInterval(this.#keepAliveInterval)\n\n window.postMessage({ type: 'msw/worker:stop' })\n },\n {\n signal: this.#listenerController?.signal,\n },\n )\n\n await this.#checkWorkerIntegrity().catch((error) => {\n devUtils.error(\n 'Error while checking the worker script integrity. Please report this on GitHub (https://github.com/mswjs/msw/issues) and include the original error below.',\n )\n console.error(error)\n })\n\n this.#keepAliveInterval = window.setInterval(() => {\n this.#channel.postMessage('KEEPALIVE_REQUEST')\n }, 5000)\n\n if (!this.#options.quiet) {\n validateWorkerScope(registration)\n }\n\n return [worker, registration] as const\n }\n\n async #handleRequest(event: WorkerChannelRequestEvent): Promise<void> {\n const request = deserializeRequest(event.data)\n RequestHandler.cache.set(request, request.clone())\n\n const frame = new ServiceWorkerHttpNetworkFrame({\n event,\n request,\n })\n this.#frames.set(event.data.id, frame)\n\n await this.queue(frame)\n }\n\n async #handleResponse(event: WorkerChannelResponseEvent): Promise<void> {\n const { request, response, isMockedResponse } = event.data\n const frame = this.#frames.get(request.id)\n\n /**\n * CORS requests with `mode: \"no-cors\"` result in \"opaque\" responses.\n * That kind of responses cannot be manipulated in JavaScript due\n * to the security considerations.\n * @see https://fetch.spec.whatwg.org/#concept-filtered-response-opaque\n * @see https://github.com/mswjs/msw/issues/529\n */\n if (response.type?.includes('opaque')) {\n this.#frames.delete(request.id)\n frame?.events.removeAllListeners()\n return\n }\n\n this.#frames.delete(request.id)\n\n /**\n * @note A request frame will be missing in case of passthrough after the worker is stopped.\n * Creating a frame is costly so it's better to handle it as an edge case here.\n */\n if (frame == null) {\n return\n }\n\n const fetchRequest = deserializeRequest(request)\n const fetchResponse =\n response.status === 0\n ? Response.error()\n : new FetchResponse(\n /**\n * Responses may be streams here, but when we create a response object\n * with null-body status codes, like 204, 205, 304 Response will\n * throw when passed a non-null body, so ensure it's null here\n * for those codes\n */\n FetchResponse.isResponseWithBody(response.status)\n ? response.body\n : null,\n {\n ...response,\n /**\n * Set response URL if it's not set already.\n * @see https://github.com/mswjs/msw/issues/2030\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/url\n */\n url: request.url,\n },\n )\n\n try {\n frame.events.emit(\n new ResponseEvent(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n requestId: frame.data.id,\n request: fetchRequest,\n response: fetchResponse,\n isMockedResponse,\n },\n ),\n )\n } finally {\n frame.events.removeAllListeners()\n }\n }\n\n /**\n * @note A request can settle without ever producing a response\n * (e.g. a passthrough request failing with a network error).\n * The worker never sends the \"RESPONSE\" message for such requests,\n * so the frame must be released here to prevent it from being retained.\n * No \"response:*\" event is emitted, consistent with the Node.js source.\n * @see https://github.com/mswjs/msw/issues/2792\n */\n #handleRequestError(event: WorkerChannelRequestErrorEvent): void {\n const { request } = event.data\n const frame = this.#frames.get(request.id)\n this.#frames.delete(request.id)\n frame?.events.removeAllListeners()\n }\n\n #defaultFindWorker: FindWorker = (workerUrl, mockServiceWorkerUrl) => {\n return workerUrl === mockServiceWorkerUrl\n }\n\n async #checkWorkerIntegrity(): Promise<void> {\n const integrityCheckPromise = Promise.withResolvers<void>()\n\n this.#channel.postMessage('INTEGRITY_CHECK_REQUEST')\n this.#channel.once('INTEGRITY_CHECK_RESPONSE', (event) => {\n const { checksum, packageVersion } = event.data\n\n // Compare the response from the Service Worker and the\n // global variable set during the build.\n\n // The integrity is validated based on the worker script's checksum\n // that's derived from its minified content during the build.\n // The \"SERVICE_WORKER_CHECKSUM\" global variable is injected by the build.\n if (checksum !== SERVICE_WORKER_CHECKSUM) {\n devUtils.warn(\n `The currently registered Service Worker has been generated by a different version of MSW (${packageVersion}) and may not be fully compatible with the installed version.\n\nIt's recommended you update your worker script by running this command:\n\n \\u2022 npx msw init <PUBLIC_DIR>\n\nYou can also automate this process and make the worker script update automatically upon the library installations. Read more: https://mswjs.io/docs/cli/init.`,\n )\n }\n\n integrityCheckPromise.resolve()\n })\n\n return integrityCheckPromise.promise\n }\n\n async #printStartMessage() {\n if (this.#workerState === 'rejected') {\n return\n }\n\n invariant(\n this.#clientPromise != null,\n '[ServiceWorkerSource] Failed to print a start message: client confirmation not received',\n )\n\n const client = await this.#clientPromise\n const [worker, registration] = await this.workerPromise\n\n console.groupCollapsed(\n `%c${devUtils.formatMessage('Mocking enabled.')}`,\n 'color:orangered;font-weight:bold;',\n )\n // eslint-disable-next-line no-console\n console.log(\n '%cDocumentation: %chttps://mswjs.io/docs',\n 'font-weight:bold',\n 'font-weight:normal',\n )\n // eslint-disable-next-line no-console\n console.log('Found an issue? https://github.com/mswjs/msw/issues')\n\n // eslint-disable-next-line no-console\n console.log('Worker script URL:', worker.scriptURL)\n\n // eslint-disable-next-line no-console\n console.log('Worker scope:', registration.scope)\n\n if (client) {\n // eslint-disable-next-line no-console\n console.log('Client ID: %s (%s)', client.id, client.frameType)\n }\n\n console.groupEnd()\n }\n\n #printStopMessage(): void {\n // eslint-disable-next-line no-console\n console.log(\n `%c${devUtils.formatMessage('Mocking disabled.')}`,\n 'color:orangered;font-weight:bold;',\n )\n }\n}\n\nclass ServiceWorkerHttpNetworkFrame extends HttpNetworkFrame {\n #event: WorkerChannelRequestEvent\n\n constructor(options: { event: WorkerChannelRequestEvent; request: Request }) {\n super({ request: options.request })\n this.#event = options.event\n }\n\n public passthrough(): void {\n // Forward the request headers so that any modifications made\n // in the request handlers are applied to the passthrough request.\n this.#event.postMessage('PASSTHROUGH', {\n request: {\n headers: Array.from(this.data.request.headers),\n },\n })\n }\n\n public respondWith(response?: Response): void {\n if (response) {\n this.#respondWith(response)\n }\n }\n\n public errorWith(reason?: unknown): void {\n if (reason instanceof Response) {\n return this.respondWith(reason)\n }\n\n devUtils.warn(\n `Uncaught exception in the request handler for \"%s %s\". This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/http/mocking-responses/error-responses`,\n this.data.request.method,\n this.data.request.url,\n )\n\n const error =\n reason instanceof Error\n ? reason\n : new Error(reason?.toString() || 'Request failure')\n\n // Treat exceptions during the request handling as 500 responses.\n // This should alert the developer that there's a problem.\n this.respondWith(\n HttpResponse.json(\n {\n name: error.name,\n message: error.message,\n stack: error.stack,\n },\n {\n status: 500,\n statusText: 'Request Handler Error',\n },\n ),\n )\n }\n\n async #respondWith(response: Response): Promise<void> {\n let responseBody: ReadableStream<Uint8Array> | ArrayBuffer | null\n let transfer: [ReadableStream<Uint8Array>] | undefined\n const responseInit = toResponseInit(response)\n\n if (supportsReadableStreamTransfer()) {\n responseBody = response.body\n transfer = response.body == null ? undefined : [response.body]\n } else {\n responseBody =\n response.body == null ? null : await response.clone().arrayBuffer()\n }\n\n this.#event.postMessage(\n 'MOCK_RESPONSE',\n {\n ...responseInit,\n body: responseBody,\n },\n transfer,\n )\n }\n}\n","import { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { InterceptorSource } from '#core/experimental/sources/interceptor-source'\nimport { devUtils } from '#core/utils/internal/dev-utils'\n\ninterface FallbackHttpSourceOptions {\n quiet?: boolean\n}\n\nexport class FallbackHttpSource extends InterceptorSource {\n constructor(private readonly options: FallbackHttpSourceOptions) {\n super({\n interceptors: [new XMLHttpRequestInterceptor(), new FetchInterceptor()],\n })\n }\n\n public enable(): void {\n super.enable()\n\n if (!this.options.quiet) {\n this.#printStartMessage()\n }\n }\n\n public disable(): void {\n super.disable()\n\n if (!this.options.quiet) {\n this.#printStopMessage()\n }\n }\n\n #printStartMessage(): void {\n console.groupCollapsed(\n `%c${devUtils.formatMessage('Mocking enabled (fallback mode).')}`,\n 'color:orangered;font-weight:bold;',\n )\n // eslint-disable-next-line no-console\n console.log(\n '%cDocumentation: %chttps://mswjs.io/docs',\n 'font-weight:bold',\n 'font-weight:normal',\n )\n // eslint-disable-next-line no-console\n console.log('Found an issue? https://github.com/mswjs/msw/issues')\n console.groupEnd()\n }\n\n #printStopMessage(): void {\n // eslint-disable-next-line no-console\n console.log(\n `%c${devUtils.formatMessage('Mocking disabled.')}`,\n 'color:orangered;font-weight:bold;',\n )\n }\n}\n","import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'\nimport {\n defineNetwork,\n NetworkReadyState,\n} from '#core/experimental/define-network'\nimport type { AnyHandler } from '#core/experimental/handlers-controller'\nimport { InterceptorSource } from '#core/experimental/sources/interceptor-source'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport { supportsServiceWorker } from './utils/supports'\nimport { ServiceWorkerSource } from './sources/service-worker-source'\nimport { FallbackHttpSource } from './sources/fallback-http-source'\nimport type { SetupWorker } from './glossary'\n\nconst DEFAULT_WORKER_URL = '/mockServiceWorker.js'\n\n/**\n * Sets up a requests interception in the browser with the given request handlers.\n * @param {Array<AnyHandler>} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-worker `setupWorker()` API reference}\n */\nexport function setupWorker(...handlers: Array<AnyHandler>): SetupWorker {\n invariant(\n !isNodeProcess(),\n devUtils.formatMessage(\n 'Failed to execute `setupWorker` in a non-browser environment',\n ),\n )\n\n const network = defineNetwork<\n Array<ServiceWorkerSource | FallbackHttpSource | InterceptorSource>\n >({\n sources: [],\n handlers,\n })\n\n return {\n get readyState() {\n return network.readyState\n },\n async start(options) {\n invariant(\n network.readyState === NetworkReadyState.DISABLED,\n devUtils.formatMessage(\n 'Failed to call \"worker.start()\": the worker is already started. Remove the redundant \"worker.start()\" call.',\n ),\n )\n\n const httpSource = supportsServiceWorker()\n ? await ServiceWorkerSource.from({\n serviceWorker: {\n url:\n options?.serviceWorker?.url?.toString() || DEFAULT_WORKER_URL,\n options: options?.serviceWorker?.options,\n },\n findWorker: options?.findWorker,\n quiet: options?.quiet,\n })\n : new FallbackHttpSource({\n quiet: options?.quiet,\n })\n\n network.configure({\n sources: [\n httpSource,\n new InterceptorSource({\n interceptors: [new WebSocketInterceptor()],\n }),\n ],\n onUnhandledFrame: options?.onUnhandledFrame ?? 'warn',\n context: {\n quiet: options?.quiet,\n },\n })\n\n await network.enable()\n\n if (httpSource instanceof ServiceWorkerSource) {\n const [, registration] = await httpSource.workerPromise\n return registration\n }\n },\n async stop() {\n await network.disable()\n window.postMessage({ type: 'msw/worker:stop' })\n },\n events: network.events,\n use: network.use.bind(network),\n resetHandlers: network.resetHandlers.bind(network),\n restoreHandlers: network.restoreHandlers.bind(network),\n listHandlers: network.listHandlers.bind(network),\n }\n}\n","import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'\nimport type { DefineNetworkOptions } from '#core/experimental/define-network'\nimport {\n InterceptorSource,\n type InterceptorSourceOptions,\n} from '#core/experimental/sources/interceptor-source'\nimport { ServiceWorkerSource } from './sources/service-worker-source'\nimport { FallbackHttpSource } from './sources/fallback-http-source'\nimport { supportsServiceWorker } from './utils/supports'\n\nexport function createDefaultNetworkOptions(\n workerUrl = '/mockServiceWorker.js',\n): DefineNetworkOptions<\n [ServiceWorkerSource | FallbackHttpSource, InterceptorSource]\n> {\n return {\n sources: [\n supportsServiceWorker()\n ? new ServiceWorkerSource({ serviceWorker: { url: workerUrl } })\n : new FallbackHttpSource({}),\n new InterceptorSource({\n interceptors: [\n new WebSocketInterceptor() as InterceptorSourceOptions['interceptors'][number],\n ],\n }),\n ],\n onUnhandledFrame: 'warn',\n }\n}\n\nexport const defaultNetworkOptions = createDefaultNetworkOptions()\n"],"mappings":";;;;;;;;;;;;;;;;;;AAIA,SAAgB,wBAAiC;CAC/C,OACE,OAAO,cAAc,eACrB,mBAAmB,aACnB,OAAO,aAAa,eACpB,SAAS,aAAa;AAE1B;;;;;;AAOA,SAAgB,iCAAiC;CAC/C,IAAI;EACF,MAAM,SAAS,IAAI,eAAe,EAChC,QAAQ,eAAe,WAAW,MAAM,EAC1C,CAAC;EAED,IADoB,eACd,CAAC,CAAC,MAAM,YAAY,QAAQ,CAAC,MAAM,CAAC;EAC1C,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;AC7BA,SAAgB,eAAe,UAAkC;CAC/D,OAAO;EACL,QAAQ,SAAS;EACjB,YAAY,SAAS;EACrB,SAAS,OAAO,YAAY,SAAS,QAAQ,QAAQ,CAAC;CACxD;AACF;;;;;;;ACFA,SAAgB,qBAAqB,WAA2B;CAC9D,OAAO,IAAI,IAAI,WAAW,SAAS,IAAI,CAAC,CAAC;AAC3C;;;;;;;ACAA,SAAgB,wBACd,cACA,mBACA,YACsB;CAetB,OARuB;EALrB,aAAa;EACb,aAAa;EACb,aAAa;CAGgB,CAAC,CAAC,QAAQ,UAAkC;EACzE,OAAO,SAAS;CAClB,CAE4B,CAAC,CAAC,MAAM,WAAW;EAC7C,OAAO,WAAW,OAAO,WAAW,iBAAiB;CACvD,CAEY,KAAK;AACnB;;;;;;;AChBA,MAAa,oBAAoB,OAC/B,KACA,UAA+B,CAAC,GAChC,eACwC;CAExC,MAAM,oBAAoB,qBAAqB,GAAG;CAElD,MAAM,oBAAoB,MAAM,UAAU,cACvC,iBAAiB,CAAC,CAClB,MAAM,kBACL,cAAc,QAAQ,iBACpB,wBAAwB,cAAc,mBAAmB,UAAU,CACrE,CACF;CACF,IAAI,CAAC,UAAU,cAAc,cAAc,kBAAkB,SAAS,GAOpE,SAAS,OAAO;CAGlB,MAAM,CAAC,wBAAwB;CAE/B,IAAI,sBAAsB;EAGxB,qBAAqB,OAAO;EAG5B,OAAO,CACL,wBACE,sBACA,mBACA,UACF,GACA,oBACF;CACF;CAGA,MAAM,CAAC,mBAAmB,sBAAsB,MAAM,MAGpD,YAAY;EACZ,MAAM,eAAe,MAAM,UAAU,cAAc,SAAS,KAAK,OAAO;EACxE,OAAO,CAGL,wBAAwB,cAAc,mBAAmB,UAAU,GACnE,YACF;CACF,CAAC;CAGD,IAAI,mBAAmB;EAKrB,IAJwB,kBAAkB,QAAQ,SAAS,OAIzC,GAAG;GACnB,MAAM,WAAW,IAAI,IAAI,SAAS,SAAS,KAAK,SAAS,IAAI;GAE7D,MAAM,IAAI,MACR,SAAS,cAAc;kDACmB,SAAS,KAAK,mBAAmB,kBAAkB;;;;oFAIjB,CAC9E;EACF;EAGA,MAAM,IAAI,MACR,SAAS,cACP,gDACA,kBAAkB,OACpB,CACF;CACF;CAEA,OAAO;AACT;;;ACTA,MAAM,0BAA0B,sBAAsB;AAEtD,IAAM,cAAN,cAIU,WAA4C;CACpD;CAEA,YAAY,aAA2B;EACrC,MAAM,OAAO,YAAY,KAAK;EAC9B,MAAM,OAAO,YAAY,KAAK;;;;;;EAO9B,MAEE,MACA,EAAE,KAAK,CACT;EACA,KAAK,eAAe;CACtB;CAEA,IAAI,QAAQ;EACV,OAAO,KAAK,aAAa;CAC3B;;;;CAKA,YACE,MACA,GAAG,MACG;EACN,KAAK,aAAa,MAAM,EAAE,CAAC,YACzB;GAAE;GAAM,MAAM,KAAK;EAAG,GACtB,EAAE,UAAU,KAAK,GAAG,CACtB;CACF;AACF;AAgBA,IAAa,gBAAb,cAAmC,QAA+B;CAChE;CACA;CAEA,YAAY,SAA+B;EACzC,MAAM;EAEN,UACE,yBACA,sFACF;EAEA,KAAK,aAAa,QAAQ;EAC1B,KAAK,cAAc,IAAI,gBAAgB;EAEvC,UAAU,cAAc,iBACtB,WACA,OAAO,UAAU;GACf,MAAM,SAAS,MAAM,KAAK,WAAW;GAErC,IAAI,MAAM,UAAU,QAAQ,MAAM,WAAW,QAC3C;GAGF,IAAI,MAAM,QAAQ,SAAS,MAAM,IAAI,KAAK,UAAU,MAAM,MACxD,KAAK,KAAK,IAAI,YAA2B,KAAK,CAAC;EAEnD,GACA,EACE,QAAQ,KAAK,YAAY,OAC3B,CACF;CACF;;;;;CAMA,YAAmB,MAAkC;EACnD,UACE,yBACA,yMACF;EAEA,KAAK,WAAW,CAAC,CAAC,MAAM,WAAW;GACjC,OAAO,YAAY,IAAI;EACzB,CAAC;CACH;;;;;CAMA,YAAyB;EACvB,KAAK,YAAY,MAAM;EACvB,KAAK,mBAAmB;CAC1B;AACF;;;;;;;ACnMA,SAAgB,mBACd,mBACS;CACT,OAAO,IAAI,aAAa,kBAAkB,KAAK,EAC7C,GAAG,kBACL,CAAC;AACH;;;;;;;;ACNA,SAAgB,oBACd,cACM;CACN,IAAI,CAAC,SAAS,KAAK,WAAW,aAAa,KAAK,GAC9C,SAAS,KACP,uFAAuF,aAAa,MAAM;;;kFAI5G;AAEJ;;;AChBA,SAAgB,uBACd,aACA,aACS;CACT,OACE,YAAY,eAAe,YAAY,cACvC,YAAY,cAAc,QAAQ,YAAY,cAAc,OAC5D,KAAK,UAAU,YAAY,cAAc,OAAO,MAC9C,KAAK,UAAU,YAAY,cAAc,OAAO;AAEtD;;;AC0CA,IAAa,sBAAb,MAAa,4BAA4B,cAA6C;CACpF,OAAO;;;;;CAMP,aAAoB,KAClB,SAC8B;EAC9B,IAAI,oBAAoB,YAAY,MAClC,oBAAoB,WAAW,IAAI,oBAAoB,OAAO;OACzD,IACL,uBAAuB,oBAAoB,SAAS,UAAU,OAAO,GACrE;GACA,MAAM,oBAAoB,SAAS,UAAU;GAC7C,oBAAoB,WAAW,IAAI,oBAAoB,OAAO;EAChE;EAEA,OAAO,oBAAoB;CAC7B;CAEA;;;;;CAKA;CACA;CACA;CACA;CACA;CAEA;CACA;CAGA;CAEA,YAAY,SAAqC;EAC/C,MAAM;EAEN,UACE,sBAAsB,GACtB,iHACF;EAEA,KAAK,WAAW;EAChB,KAAK,0BAAU,IAAI,IAAI;EACvB,KAAK,mBAAmB,QAAQ,cAAc;EAC9C,KAAK,gBAAgB,KAAK,iBAAiB;EAC3C,KAAK,eAAe;EACpB,KAAK,WAAW,IAAI,cAAc,EAChC,iBAAiB,KAAK,cAAc,MAAM,CAAC,YAAY,MAAM,EAC/D,CAAC;CACH;CAEA,MAAa,SAA6C;EACxD,KAAK,SAAS,mBAAmB;EACjC,KAAK,QAAQ,MAAM;EAEnB,KAAK,sBAAsB,IAAI,gBAAgB;EAC/C,MAAM,CAAC,QAAQ,gBAAgB,MAAM,KAAK,aAAa;EAEvD,IAAI,OAAO,UAAU,aAAa;GAChC,MAAM,aAAa,IAAI,gBAAgB;GACvC,MAAM,oBAAoB,QAAQ,cAAoB;GACtD,kBAAkB,QAAQ,WAAW,WAAW,MAAM,CAAC;GAEvD,OAAO,iBACL,qBACM;IACJ,IAAI,OAAO,UAAU,aACnB,kBAAkB,QAAQ;GAE9B,GACA,EACE,QAAQ,WAAW,OACrB,CACF;GAEA,MAAM,kBAAkB;EAC1B;EAEA,KAAK,SAAS,YAAY,eAAe;EAEzC,MAAM,4BACJ,QAAQ,cAAmC;EAC7C,KAAK,iBAAiB,0BAA0B;EAEhD,KAAK,SAAS,KAAK,oBAAoB,UAAU;GAC/C,0BAA0B,QAAQ,MAAM,KAAK,MAAM;EACrD,CAAC;EACD,MAAM,0BAA0B;EAEhC,IAAI,CAAC,KAAK,SAAS,OACjB,KAAK,mBAAmB;EAG1B,OAAO;CACT;CAEA,MAAa,UAAyB;;;;;;;EAQpC,KAAK,qBAAqB,MAAM;EAChC,KAAK,sBAAsB,KAAA;EAE3B,MAAM,gBAAgB,QAAQ,cAAoB;EAClD,KAAK,SAAS,KAAK,uBAAuB,cAAc,QAAQ,CAAC;EAEjE,KAAK,SAAS,YAAY,cAAc;EACxC,MAAM,cAAc;;;;;;;EASpB,IAAI,CAAC,KAAK,SAAS,OACjB,KAAK,kBAAkB;CAE3B;;;;;;CAOA,MAAa,YAA2B;EACtC,IAAI,KAAK,sBAAsB,MAAM;GACnC,cAAc,KAAK,kBAAkB;GACrC,KAAK,qBAAqB,KAAA;EAC5B;EAEA,KAAK,QAAQ,MAAM;EACnB,KAAK,SAAS,UAAU;EACxB,KAAK,qBAAqB,MAAM;EAChC,KAAK,sBAAsB,KAAA;EAE3B,IAAI,KAAK,iBAAiB,aAAa;GACrC,MAAM,GAAG,gBAAgB,MAAM,KAAK;GACpC,MAAM,aAAa,WAAW;EAChC;EAEA,IAAI,oBAAoB,aAAa,MACnC,oBAAoB,WAAW,KAAA;CAEnC;CAEA,MAAM,eAAe;EACnB,IAAI,KAAK,oBACP,cAAc,KAAK,kBAAkB;EAGvC,MAAM,YAAY,KAAK,SAAS,cAAc;EAE9C,MAAM,CAAC,QAAQ,gBAAgB,MAAM,kBACnC,WACA,KAAK,SAAS,cAAc,SAC5B,KAAK,SAAS,cAAc,KAAK,kBACnC;EAEA,IAAI,UAAU,MAAM;GAClB,MAAM,uBAAuB,KAAK,UAAU,aACxC,SAAS,cACP;;;;QAKA,SACF,IACA,SAAS,cACP;;;;2PAKA,WACA,SAAS,IACX;GAEJ,MAAM,IAAI,MAAM,oBAAoB;EACtC;EAEA,IAAI,KAAK,iBAAiB,WAAW;GACnC,KAAK,iBAAiB,QAAQ,CAAC,QAAQ,YAAY,CAAC;GACpD,KAAK,eAAe;EACtB,OAAO;;;;;;GAML,KAAK,mBAAmB,QAAQ,cAAc;GAC9C,KAAK,iBAAiB,QAAQ,CAAC,QAAQ,YAAY,CAAC;GACpD,KAAK,gBAAgB,KAAK,iBAAiB;EAC7C;EAEA,KAAK,SAAS,GAAG,WAAW,KAAK,eAAe,KAAK,IAAI,CAAC;EAC1D,KAAK,SAAS,GAAG,YAAY,KAAK,gBAAgB,KAAK,IAAI,CAAC;EAC5D,KAAK,SAAS,GAAG,iBAAiB,KAAK,oBAAoB,KAAK,IAAI,CAAC;EAErE,OAAO,iBACL,aACC,UAAU;GACT,IAAI,MAAM,WACR;GAGF,IAAI,OAAO,UAAU,aACnB,KAAK,SAAS,YAAY,cAAc;GAG1C,cAAc,KAAK,kBAAkB;GAErC,OAAO,YAAY,EAAE,MAAM,kBAAkB,CAAC;EAChD,GACA,EACE,QAAQ,KAAK,qBAAqB,OACpC,CACF;EAEA,MAAM,KAAK,sBAAsB,CAAC,CAAC,OAAO,UAAU;GAClD,SAAS,MACP,4JACF;GACA,QAAQ,MAAM,KAAK;EACrB,CAAC;EAED,KAAK,qBAAqB,OAAO,kBAAkB;GACjD,KAAK,SAAS,YAAY,mBAAmB;EAC/C,GAAG,GAAI;EAEP,IAAI,CAAC,KAAK,SAAS,OACjB,oBAAoB,YAAY;EAGlC,OAAO,CAAC,QAAQ,YAAY;CAC9B;CAEA,MAAM,eAAe,OAAiD;EACpE,MAAM,UAAU,mBAAmB,MAAM,IAAI;EAC7C,eAAe,MAAM,IAAI,SAAS,QAAQ,MAAM,CAAC;EAEjD,MAAM,QAAQ,IAAI,8BAA8B;GAC9C;GACA;EACF,CAAC;EACD,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,KAAK;EAErC,MAAM,KAAK,MAAM,KAAK;CACxB;CAEA,MAAM,gBAAgB,OAAkD;EACtE,MAAM,EAAE,SAAS,UAAU,qBAAqB,MAAM;EACtD,MAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ,EAAE;;;;;;;;EASzC,IAAI,SAAS,MAAM,SAAS,QAAQ,GAAG;GACrC,KAAK,QAAQ,OAAO,QAAQ,EAAE;GAC9B,OAAO,OAAO,mBAAmB;GACjC;EACF;EAEA,KAAK,QAAQ,OAAO,QAAQ,EAAE;;;;;EAM9B,IAAI,SAAS,MACX;EAGF,MAAM,eAAe,mBAAmB,OAAO;EAC/C,MAAM,gBACJ,SAAS,WAAW,IAChB,SAAS,MAAM,IACf,IAAI;;;;;;;GAOF,cAAc,mBAAmB,SAAS,MAAM,IAC5C,SAAS,OACT;GACJ;IACE,GAAG;;;;;;IAMH,KAAK,QAAQ;GACf;EACF;EAEN,IAAI;GACF,MAAM,OAAO,KACX,IAAI,cACF,mBAAmB,oBAAoB,mBACvC;IACE,WAAW,MAAM,KAAK;IACtB,SAAS;IACT,UAAU;IACV;GACF,CACF,CACF;EACF,UAAU;GACR,MAAM,OAAO,mBAAmB;EAClC;CACF;;;;;;;;;CAUA,oBAAoB,OAA6C;EAC/D,MAAM,EAAE,YAAY,MAAM;EAC1B,MAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ,EAAE;EACzC,KAAK,QAAQ,OAAO,QAAQ,EAAE;EAC9B,OAAO,OAAO,mBAAmB;CACnC;CAEA,sBAAkC,WAAW,yBAAyB;EACpE,OAAO,cAAc;CACvB;CAEA,MAAM,wBAAuC;EAC3C,MAAM,wBAAwB,QAAQ,cAAoB;EAE1D,KAAK,SAAS,YAAY,yBAAyB;EACnD,KAAK,SAAS,KAAK,6BAA6B,UAAU;GACxD,MAAM,EAAE,UAAU,mBAAmB,MAAM;GAQ3C,IAAI,aAAA,oCACF,SAAS,KACP,6FAA6F,eAAe;;;;;;8JAO9G;GAGF,sBAAsB,QAAQ;EAChC,CAAC;EAED,OAAO,sBAAsB;CAC/B;CAEA,MAAM,qBAAqB;EACzB,IAAI,KAAK,iBAAiB,YACxB;EAGF,UACE,KAAK,kBAAkB,MACvB,yFACF;EAEA,MAAM,SAAS,MAAM,KAAK;EAC1B,MAAM,CAAC,QAAQ,gBAAgB,MAAM,KAAK;EAE1C,QAAQ,eACN,KAAK,SAAS,cAAc,kBAAkB,KAC9C,mCACF;EAEA,QAAQ,IACN,4CACA,oBACA,oBACF;EAEA,QAAQ,IAAI,qDAAqD;EAGjE,QAAQ,IAAI,sBAAsB,OAAO,SAAS;EAGlD,QAAQ,IAAI,iBAAiB,aAAa,KAAK;EAE/C,IAAI,QAEF,QAAQ,IAAI,sBAAsB,OAAO,IAAI,OAAO,SAAS;EAG/D,QAAQ,SAAS;CACnB;CAEA,oBAA0B;EAExB,QAAQ,IACN,KAAK,SAAS,cAAc,mBAAmB,KAC/C,mCACF;CACF;AACF;AAEA,IAAM,gCAAN,cAA4C,iBAAiB;CAC3D;CAEA,YAAY,SAAiE;EAC3E,MAAM,EAAE,SAAS,QAAQ,QAAQ,CAAC;EAClC,KAAK,SAAS,QAAQ;CACxB;CAEA,cAA2B;EAGzB,KAAK,OAAO,YAAY,eAAe,EACrC,SAAS,EACP,SAAS,MAAM,KAAK,KAAK,KAAK,QAAQ,OAAO,EAC/C,EACF,CAAC;CACH;CAEA,YAAmB,UAA2B;EAC5C,IAAI,UACF,KAAK,aAAa,QAAQ;CAE9B;CAEA,UAAiB,QAAwB;EACvC,IAAI,kBAAkB,UACpB,OAAO,KAAK,YAAY,MAAM;EAGhC,SAAS,KACP,qVACA,KAAK,KAAK,QAAQ,QAClB,KAAK,KAAK,QAAQ,GACpB;EAEA,MAAM,QACJ,kBAAkB,QACd,SACA,IAAI,MAAM,QAAQ,SAAS,KAAK,iBAAiB;EAIvD,KAAK,YACH,aAAa,KACX;GACE,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,OAAO,MAAM;EACf,GACA;GACE,QAAQ;GACR,YAAY;EACd,CACF,CACF;CACF;CAEA,MAAM,aAAa,UAAmC;EACpD,IAAI;EACJ,IAAI;EACJ,MAAM,eAAe,eAAe,QAAQ;EAE5C,IAAI,+BAA+B,GAAG;GACpC,eAAe,SAAS;GACxB,WAAW,SAAS,QAAQ,OAAO,KAAA,IAAY,CAAC,SAAS,IAAI;EAC/D,OACE,eACE,SAAS,QAAQ,OAAO,OAAO,MAAM,SAAS,MAAM,CAAC,CAAC,YAAY;EAGtE,KAAK,OAAO,YACV,iBACA;GACE,GAAG;GACH,MAAM;EACR,GACA,QACF;CACF;AACF;;;AC1iBA,IAAa,qBAAb,cAAwC,kBAAkB;CAC3B;CAA7B,YAAY,SAAqD;EAC/D,MAAM,EACJ,cAAc,CAAC,IAAI,0BAA0B,GAAG,IAAI,iBAAiB,CAAC,EACxE,CAAC;EAH0B,KAAA,UAAA;CAI7B;CAEA,SAAsB;EACpB,MAAM,OAAO;EAEb,IAAI,CAAC,KAAK,QAAQ,OAChB,KAAK,mBAAmB;CAE5B;CAEA,UAAuB;EACrB,MAAM,QAAQ;EAEd,IAAI,CAAC,KAAK,QAAQ,OAChB,KAAK,kBAAkB;CAE3B;CAEA,qBAA2B;EACzB,QAAQ,eACN,KAAK,SAAS,cAAc,kCAAkC,KAC9D,mCACF;EAEA,QAAQ,IACN,4CACA,oBACA,oBACF;EAEA,QAAQ,IAAI,qDAAqD;EACjE,QAAQ,SAAS;CACnB;CAEA,oBAA0B;EAExB,QAAQ,IACN,KAAK,SAAS,cAAc,mBAAmB,KAC/C,mCACF;CACF;AACF;;;ACxCA,MAAM,qBAAqB;;;;;;;AAQ3B,SAAgB,YAAY,GAAG,UAA0C;CACvE,UACE,CAAC,cAAc,GACf,SAAS,cACP,8DACF,CACF;CAEA,MAAM,UAAU,cAEd;EACA,SAAS,CAAC;EACV;CACF,CAAC;CAED,OAAO;EACL,IAAI,aAAa;GACf,OAAO,QAAQ;EACjB;EACA,MAAM,MAAM,SAAS;GACnB,UACE,QAAQ,eAAA,GACR,SAAS,cACP,iHACF,CACF;GAEA,MAAM,aAAa,sBAAsB,IACrC,MAAM,oBAAoB,KAAK;IAC7B,eAAe;KACb,KACE,SAAS,eAAe,KAAK,SAAS,KAAK;KAC7C,SAAS,SAAS,eAAe;IACnC;IACA,YAAY,SAAS;IACrB,OAAO,SAAS;GAClB,CAAC,IACD,IAAI,mBAAmB,EACrB,OAAO,SAAS,MAClB,CAAC;GAEL,QAAQ,UAAU;IAChB,SAAS,CACP,YACA,IAAI,kBAAkB,EACpB,cAAc,CAAC,IAAI,qBAAqB,CAAC,EAC3C,CAAC,CACH;IACA,kBAAkB,SAAS,oBAAoB;IAC/C,SAAS,EACP,OAAO,SAAS,MAClB;GACF,CAAC;GAED,MAAM,QAAQ,OAAO;GAErB,IAAI,sBAAsB,qBAAqB;IAC7C,MAAM,GAAG,gBAAgB,MAAM,WAAW;IAC1C,OAAO;GACT;EACF;EACA,MAAM,OAAO;GACX,MAAM,QAAQ,QAAQ;GACtB,OAAO,YAAY,EAAE,MAAM,kBAAkB,CAAC;EAChD;EACA,QAAQ,QAAQ;EAChB,KAAK,QAAQ,IAAI,KAAK,OAAO;EAC7B,eAAe,QAAQ,cAAc,KAAK,OAAO;EACjD,iBAAiB,QAAQ,gBAAgB,KAAK,OAAO;EACrD,cAAc,QAAQ,aAAa,KAAK,OAAO;CACjD;AACF;;;ACpFA,SAAgB,4BACd,YAAY,yBAGZ;CACA,OAAO;EACL,SAAS,CACP,sBAAsB,IAClB,IAAI,oBAAoB,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,CAAC,IAC7D,IAAI,mBAAmB,CAAC,CAAC,GAC7B,IAAI,kBAAkB,EACpB,cAAc,CACZ,IAAI,qBAAqB,CAC3B,EACF,CAAC,CACH;EACA,kBAAkB;CACpB;AACF;AAEA,MAAa,wBAAwB,4BAA4B"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/browser/utils/supports.ts","../../src/core/utils/to-response-init.ts","../../src/browser/utils/get-absolute-worker-url.ts","../../src/browser/utils/get-worker-by-registration.ts","../../src/browser/utils/get-worker-instance.ts","../../src/browser/utils/worker-channel.ts","../../src/browser/utils/deserialize-request.ts","../../src/browser/utils/validate-worker-scope.ts","../../src/browser/utils/should-invalidate-worker.ts","../../src/browser/sources/service-worker-source.ts","../../src/browser/sources/fallback-http-source.ts","../../src/browser/setup-worker.ts","../../src/browser/default-network-options.ts"],"sourcesContent":["/**\n * Checks if the Service Worker API is supproted and available\n * in the current browsing context.\n */\nexport function supportsServiceWorker(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n 'serviceWorker' in navigator &&\n typeof location !== 'undefined' &&\n location.protocol !== 'file:'\n )\n}\n\n/**\n * Returns a boolean indicating whether the current browser\n * supports `ReadableStream` as a `Transferable` when posting\n * messages.\n */\nexport function supportsReadableStreamTransfer() {\n try {\n const stream = new ReadableStream({\n start: (controller) => controller.close(),\n })\n const message = new MessageChannel()\n message.port1.postMessage(stream, [stream])\n return true\n } catch {\n return false\n }\n}\n","export function toResponseInit(response: Response): ResponseInit {\n return {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n }\n}\n","/**\n * Returns an absolute Service Worker URL based on the given\n * relative URL (known during the registration).\n */\nexport function getAbsoluteWorkerUrl(workerUrl: string): string {\n return new URL(workerUrl, location.href).href\n}\n","import type { FindWorker } from '../glossary'\n\n/**\n * Attempts to resolve a Service Worker instance from a given registration,\n * regardless of its state (active, installing, waiting).\n */\nexport function getWorkerByRegistration(\n registration: ServiceWorkerRegistration,\n absoluteWorkerUrl: string,\n findWorker: FindWorker,\n): ServiceWorker | null {\n const allStates = [\n registration.active,\n registration.installing,\n registration.waiting,\n ]\n\n const relevantStates = allStates.filter((state): state is ServiceWorker => {\n return state != null\n })\n\n const worker = relevantStates.find((worker) => {\n return findWorker(worker.scriptURL, absoluteWorkerUrl)\n })\n\n return worker || null\n}\n","import { until } from 'until-async'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport { getAbsoluteWorkerUrl } from './get-absolute-worker-url'\nimport { getWorkerByRegistration } from './get-worker-by-registration'\nimport type { ServiceWorkerInstanceTuple, FindWorker } from '../glossary'\n\n/**\n * Returns an active Service Worker instance.\n * When not found, registers a new Service Worker.\n */\nexport const getWorkerInstance = async (\n url: string,\n options: RegistrationOptions = {},\n findWorker: FindWorker,\n): Promise<ServiceWorkerInstanceTuple> => {\n // Resolve the absolute Service Worker URL.\n const absoluteWorkerUrl = getAbsoluteWorkerUrl(url)\n\n const mockRegistrations = await navigator.serviceWorker\n .getRegistrations()\n .then((registrations) =>\n registrations.filter((registration) =>\n getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),\n ),\n )\n if (!navigator.serviceWorker.controller && mockRegistrations.length > 0) {\n // Reload the page when it has associated workers, but no active controller.\n // The absence of a controller can mean either:\n // - page has no Service Worker associated with it\n // - page has been hard-reloaded and its workers won't be used until the next reload.\n // Since we've checked that there are registrations associated with this page,\n // at this point we are sure it's hard reload that falls into this clause.\n location.reload()\n }\n\n const [existingRegistration] = mockRegistrations\n\n if (existingRegistration) {\n // Schedule the worker update in the background.\n // Update ensures the existing worker is up-to-date.\n existingRegistration.update()\n\n // Return the worker reference immediately.\n return [\n getWorkerByRegistration(\n existingRegistration,\n absoluteWorkerUrl,\n findWorker,\n ),\n existingRegistration,\n ]\n }\n\n // When the Service Worker wasn't found, register it anew and return the reference.\n const [registrationError, registrationResult] = await until<\n Error,\n ServiceWorkerInstanceTuple\n >(async () => {\n const registration = await navigator.serviceWorker.register(url, options)\n return [\n // Compare existing worker registration by its worker URL,\n // to prevent irrelevant workers to resolve here (such as Codesandbox worker).\n getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),\n registration,\n ]\n })\n\n // Handle Service Worker registration errors.\n if (registrationError) {\n const isWorkerMissing = registrationError.message.includes('(404)')\n\n // Produce a custom error message when given a non-existing Service Worker url.\n // Suggest developers to check their setup.\n if (isWorkerMissing) {\n const scopeUrl = new URL(options?.scope || '/', location.href)\n\n throw new Error(\n devUtils.formatMessage(`\\\nFailed to register a Service Worker for scope ('${scopeUrl.href}') with script ('${absoluteWorkerUrl}'): Service Worker script does not exist at the given path.\n\nDid you forget to run \"npx msw init <PUBLIC_DIR>\"?\n\nLearn more about creating the Service Worker script: https://mswjs.io/docs/cli/init`),\n )\n }\n\n // Fallback error message for any other registration errors.\n throw new Error(\n devUtils.formatMessage(\n 'Failed to register the Service Worker:\\n\\n%s',\n registrationError.message,\n ),\n )\n }\n\n return registrationResult\n}\n","import { invariant } from 'outvariant'\nimport { Emitter, TypedEvent } from 'rettime'\nimport { isObject } from '#core/utils/internal/is-object'\nimport type { StringifiedResponse } from '../glossary'\nimport { supportsServiceWorker } from '../utils/supports'\n\nexport type WorkerChannelEventMap = {\n REQUEST: WorkerEvent<IncomingWorkerRequest>\n RESPONSE: WorkerEvent<IncomingWorkerResponse>\n REQUEST_ERROR: WorkerEvent<IncomingWorkerRequestError>\n MOCKING_ENABLED: WorkerEvent<{\n client: {\n id: string\n frameType: string\n }\n }>\n CLIENT_CLOSED: TypedEvent<never>\n INTEGRITY_CHECK_RESPONSE: WorkerEvent<{\n packageVersion: string\n checksum: string\n }>\n KEEPALIVE_RESPONSE: TypedEvent<never>\n}\n\n/**\n * Request representation received from the worker message event.\n */\nexport interface IncomingWorkerRequest extends Omit<\n Request,\n | 'text'\n | 'body'\n | 'json'\n | 'blob'\n | 'arrayBuffer'\n | 'formData'\n | 'clone'\n | 'signal'\n | 'isHistoryNavigation'\n | 'isReloadNavigation'\n> {\n /**\n * Unique ID of the request generated once the request is\n * intercepted by the \"fetch\" event in the Service Worker.\n */\n id: string\n body?: ArrayBuffer | null\n}\n\ntype IncomingWorkerResponse = {\n isMockedResponse: boolean\n request: IncomingWorkerRequest\n response: Pick<\n Response,\n 'type' | 'ok' | 'status' | 'statusText' | 'body' | 'headers' | 'redirected'\n >\n}\n\n/**\n * Notification that a request has settled without producing a response\n * (e.g. a passthrough request failed with a network error).\n */\ntype IncomingWorkerRequestError = {\n request: Pick<IncomingWorkerRequest, 'id'>\n error: Pick<Error, 'name' | 'message'>\n}\n\n/**\n * Request modifications to apply to the passthrough request in the worker.\n */\nexport interface PassthroughPayload {\n request: {\n /**\n * Request headers as a list of entries to support\n * multiple headers with the same name.\n */\n headers: Array<[string, string]>\n }\n}\n\ntype WorkerEventResponse = {\n MOCK_RESPONSE: [\n data: StringifiedResponse,\n transfer?: [ReadableStream<Uint8Array>],\n ]\n PASSTHROUGH: [data: PassthroughPayload]\n}\n\nconst SUPPORTS_SERVICE_WORKER = supportsServiceWorker()\n\nclass WorkerEvent<\n DataType,\n ReturnType = any,\n EventType extends string = string,\n> extends TypedEvent<DataType, ReturnType, EventType> {\n #workerEvent: MessageEvent\n\n constructor(workerEvent: MessageEvent) {\n const type = workerEvent.data.type as EventType\n const data = workerEvent.data.payload as DataType\n\n /**\n * @note This is the only place we're mapping { type, payload }\n * message structure of the worker. The client references the\n * payload via `event.data`.\n */\n super(\n // @ts-expect-error Troublesome `TypedEvent` extension.\n type,\n { data },\n )\n this.#workerEvent = workerEvent\n }\n\n get ports() {\n return this.#workerEvent.ports\n }\n\n /**\n * Reply directly to this event using its `MessagePort`.\n */\n public postMessage<Type extends keyof WorkerEventResponse>(\n type: Type,\n ...rest: WorkerEventResponse[Type]\n ): void {\n this.#workerEvent.ports[0].postMessage(\n { type, data: rest[0] },\n { transfer: rest[1] },\n )\n }\n}\n\n/**\n * Map of the events that can be sent to the Service Worker\n * from any execution context.\n */\ntype OutgoingWorkerEvents =\n | 'MOCK_ACTIVATE'\n | 'INTEGRITY_CHECK_REQUEST'\n | 'KEEPALIVE_REQUEST'\n | 'CLIENT_CLOSE'\n\nexport interface WorkerChannelOptions {\n getWorker: () => Promise<ServiceWorker>\n}\n\nexport class WorkerChannel extends Emitter<WorkerChannelEventMap> {\n #getWorker: WorkerChannelOptions['getWorker']\n #controller: AbortController\n\n constructor(options: WorkerChannelOptions) {\n super()\n\n invariant(\n SUPPORTS_SERVICE_WORKER,\n 'Failed to open a WorkerChannel: Service Worker is not supported in this environment.',\n )\n\n this.#getWorker = options.getWorker\n this.#controller = new AbortController()\n\n navigator.serviceWorker.addEventListener(\n 'message',\n async (event) => {\n const worker = await this.#getWorker()\n\n if (event.source != null && event.source !== worker) {\n return\n }\n\n if (event.data && isObject(event.data) && 'type' in event.data) {\n this.emit(new WorkerEvent<any, any, any>(event))\n }\n },\n {\n signal: this.#controller.signal,\n },\n )\n }\n\n /**\n * Send data to the Service Worker controlling this client.\n * This triggers the `message` event listener on ServiceWorkerGlobalScope.\n */\n public postMessage(type: OutgoingWorkerEvents): void {\n invariant(\n SUPPORTS_SERVICE_WORKER,\n 'Failed to post message on a WorkerChannel: the Service Worker API is unavailable in this environment. This is likely an issue with MSW. Please report it on GitHub: https://github.com/mswjs/msw/issues',\n )\n\n this.#getWorker().then((worker) => {\n worker.postMessage(type)\n })\n }\n\n /**\n * Terminal teardown. Removes the `navigator.serviceWorker` message listener\n * and all emitter subscriptions. The channel is not usable afterwards.\n */\n public terminate(): void {\n this.#controller.abort()\n this.removeAllListeners()\n }\n}\n","import { FetchRequest } from '@mswjs/interceptors'\nimport type { IncomingWorkerRequest } from './worker-channel'\n\n/**\n * Converts a given request received from the Service Worker\n * into a Fetch `Request` instance.\n */\nexport function deserializeRequest(\n serializedRequest: IncomingWorkerRequest,\n): Request {\n return new FetchRequest(serializedRequest.url, {\n ...serializedRequest,\n })\n}\n","import { devUtils } from '#core/utils/internal/dev-utils'\n\n/**\n * Print a warning if the given Service Worker registration has a scope\n * outside of the current page's location. That is to help with debugging\n * issues caused by the incorrectly registered Service Worker.\n */\nexport function validateWorkerScope(\n registration: ServiceWorkerRegistration,\n): void {\n if (!location.href.startsWith(registration.scope)) {\n devUtils.warn(\n `Cannot intercept requests on this page because it's outside of the worker's scope (\"${registration.scope}\"). If you wish to mock API requests on this page, you must resolve this scope issue.\n\n- (Recommended) Register the worker at the root level (\"/\") of your application.\n- Set the \"Service-Worker-Allowed\" response header to allow out-of-scope workers.`,\n )\n }\n}\n","import type { ServiceWorkerSourceOptions } from '../sources/service-worker-source'\n\nexport function shouldInvalidateWorker(\n prevOptions: ServiceWorkerSourceOptions,\n nextOptions: ServiceWorkerSourceOptions,\n): boolean {\n return (\n prevOptions.findWorker !== nextOptions.findWorker ||\n prevOptions.serviceWorker.url !== nextOptions.serviceWorker.url ||\n JSON.stringify(prevOptions.serviceWorker.options) !==\n JSON.stringify(nextOptions.serviceWorker.options)\n )\n}\n","import { invariant } from 'outvariant'\nimport type { Emitter } from 'rettime'\nimport { FetchResponse } from '@mswjs/interceptors'\nimport { NetworkSource } from '#core/experimental/sources/network-source'\nimport type { NetworkFrameResolutionContext } from '#core/experimental/frames/network-frame'\nimport { RequestHandler } from '#core/handlers/request-handler'\nimport {\n HttpNetworkFrame,\n ResponseEvent,\n} from '#core/experimental/frames/http-frame'\nimport { HttpResponse } from '#http/http-response'\nimport { toResponseInit } from '#core/utils/to-response-init'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport {\n supportsReadableStreamTransfer,\n supportsServiceWorker,\n} from '../utils/supports'\nimport { getWorkerInstance } from '../utils/get-worker-instance'\nimport type { WorkerChannelEventMap } from '../utils/worker-channel'\nimport { WorkerChannel } from '../utils/worker-channel'\nimport type { FindWorker } from '../glossary'\nimport { deserializeRequest } from '../utils/deserialize-request'\nimport { validateWorkerScope } from '../utils/validate-worker-scope'\nimport { shouldInvalidateWorker } from '../utils/should-invalidate-worker'\n\nexport interface ServiceWorkerSourceOptions {\n serviceWorker: {\n url: string\n options?: RegistrationOptions\n }\n findWorker?: FindWorker\n}\n\ntype WorkerChannelRequestEvent = Emitter.Event<\n WorkerChannel,\n 'REQUEST',\n WorkerChannelEventMap\n>\n\ntype WorkerChannelResponseEvent = Emitter.Event<\n WorkerChannel,\n 'RESPONSE',\n WorkerChannelEventMap\n>\n\ntype WorkerChannelRequestErrorEvent = Emitter.Event<\n WorkerChannel,\n 'REQUEST_ERROR',\n WorkerChannelEventMap\n>\n\ntype WorkerChannelClient =\n WorkerChannelEventMap['MOCKING_ENABLED']['data']['client']\n\nexport class ServiceWorkerSource extends NetworkSource<ServiceWorkerHttpNetworkFrame> {\n static #current?: ServiceWorkerSource\n\n /**\n * Create a new Service Worker source or reuse an existing one.\n * These sources act as a singleton and only get recreated if the options change.\n */\n public static async from(\n options: ServiceWorkerSourceOptions,\n ): Promise<ServiceWorkerSource> {\n if (ServiceWorkerSource.#current == null) {\n ServiceWorkerSource.#current = new ServiceWorkerSource(options)\n } else if (\n shouldInvalidateWorker(ServiceWorkerSource.#current.#options, options)\n ) {\n await ServiceWorkerSource.#current.terminate()\n ServiceWorkerSource.#current = new ServiceWorkerSource(options)\n }\n\n return ServiceWorkerSource.#current\n }\n\n #options: ServiceWorkerSourceOptions\n /**\n * The resolved context of the network this source was last enabled with.\n */\n #context?: NetworkFrameResolutionContext\n /**\n * @note We cannot use `WeakMap` here as request/response\n * identity cannot be preserved through the client-worker channel.\n */\n #frames: Map<string, ServiceWorkerHttpNetworkFrame>\n #channel: WorkerChannel\n #listenerController?: AbortController\n #clientPromise?: Promise<WorkerChannelClient>\n #keepAliveInterval?: number\n\n public workerPromise: Promise<[ServiceWorker, ServiceWorkerRegistration]>\n #workerResolvers: PromiseWithResolvers<\n [ServiceWorker, ServiceWorkerRegistration]\n >\n #workerState: 'pending' | 'fulfilled' | 'rejected'\n\n constructor(options: ServiceWorkerSourceOptions) {\n super()\n\n invariant(\n supportsServiceWorker(),\n 'Failed to use Service Worker as the network source: the Service Worker API is not supported in this environment',\n )\n\n this.#options = options\n this.#frames = new Map()\n this.#workerResolvers = Promise.withResolvers()\n this.workerPromise = this.#workerResolvers.promise\n this.#workerState = 'pending'\n this.#channel = new WorkerChannel({\n getWorker: () => this.workerPromise.then(([worker]) => worker),\n })\n }\n\n public async enable(\n context?: NetworkFrameResolutionContext,\n ): Promise<ServiceWorkerRegistration> {\n this.#context = context\n this.#channel.removeAllListeners()\n this.#frames.clear()\n\n this.#listenerController = new AbortController()\n const [worker, registration] = await this.#startWorker()\n\n if (worker.state !== 'activated') {\n const controller = new AbortController()\n const activationPromise = Promise.withResolvers<void>()\n activationPromise.promise.then(() => controller.abort())\n\n worker.addEventListener(\n 'statechange',\n () => {\n if (worker.state === 'activated') {\n activationPromise.resolve()\n }\n },\n {\n signal: controller.signal,\n },\n )\n\n await activationPromise.promise\n }\n\n this.#channel.postMessage('MOCK_ACTIVATE')\n\n const clientConfirmationPromise =\n Promise.withResolvers<WorkerChannelClient>()\n this.#clientPromise = clientConfirmationPromise.promise\n\n this.#channel.once('MOCKING_ENABLED', (event) => {\n clientConfirmationPromise.resolve(event.data.client)\n })\n await clientConfirmationPromise.promise\n\n if (!this.#context?.quiet) {\n this.#printStartMessage()\n }\n\n return registration\n }\n\n public async disable(): Promise<void> {\n /**\n * @note Do NOT call `super.disable()` because it removes any \"frame\" listeners\n * from this network source, effectively turning it off. The Service Worker source\n * is a bit special since it might process in-flight requests that have been performed\n * after it's been disabled.\n */\n\n this.#listenerController?.abort()\n this.#listenerController = undefined\n\n const closedPromise = Promise.withResolvers<void>()\n this.#channel.once('CLIENT_CLOSED', () => closedPromise.resolve())\n\n this.#channel.postMessage('CLIENT_CLOSE')\n await closedPromise.promise\n\n /**\n * @note Do NOT reset `workerPromise` here. The channel must continue to\n * resolve the currently registered SW so that any in-flight requests the\n * worker forwards after `stop()` can be answered with `PASSTHROUGH` by\n * `#handleRequest`. `#startWorker` swaps in a fresh deferred on re-enable.\n */\n\n if (!this.#context?.quiet) {\n this.#printStopMessage()\n }\n }\n\n /**\n * Terminal teardown. Unregisters the Service Worker, tears down the channel,\n * and clears timers. Called when the singleton is being replaced with one\n * that has different options. The instance is not usable afterwards.\n */\n public async terminate(): Promise<void> {\n if (this.#keepAliveInterval != null) {\n clearInterval(this.#keepAliveInterval)\n this.#keepAliveInterval = undefined\n }\n\n this.#frames.clear()\n this.#channel.terminate()\n this.#listenerController?.abort()\n this.#listenerController = undefined\n\n if (this.#workerState === 'fulfilled') {\n const [, registration] = await this.workerPromise\n await registration.unregister()\n }\n\n if (ServiceWorkerSource.#current === this) {\n ServiceWorkerSource.#current = undefined\n }\n }\n\n async #startWorker() {\n if (this.#keepAliveInterval) {\n clearInterval(this.#keepAliveInterval)\n }\n\n const workerUrl = this.#options.serviceWorker.url\n\n const [worker, registration] = await getWorkerInstance(\n workerUrl,\n this.#options.serviceWorker.options,\n this.#options.findWorker || this.#defaultFindWorker,\n )\n\n if (worker == null) {\n const missingWorkerMessage = this.#options?.findWorker\n ? devUtils.formatMessage(\n `Failed to locate the Service Worker registration using a custom \"findWorker\" predicate.\n\nPlease ensure that the custom predicate properly locates the Service Worker registration at \"%s\".\nMore details: https://mswjs.io/docs/api/setup-worker/start#findworker\n `,\n workerUrl,\n )\n : devUtils.formatMessage(\n `Failed to locate the Service Worker registration.\n\nThis most likely means that the worker script URL \"%s\" cannot resolve against the actual public hostname (%s). This may happen if your application runs behind a proxy, or has a dynamic hostname.\n\nPlease consider using a custom \"serviceWorker.url\" option to point to the actual worker script location, or a custom \"findWorker\" option to resolve the Service Worker registration manually. More details: https://mswjs.io/docs/api/setup-worker/start`,\n workerUrl,\n location.host,\n )\n\n throw new Error(missingWorkerMessage)\n }\n\n if (this.#workerState === 'pending') {\n this.#workerResolvers.resolve([worker, registration])\n this.#workerState = 'fulfilled'\n } else {\n /**\n * @note Re-enable after `stop()`: the previous `workerPromise` is already\n * fulfilled and cannot be resolved again. Swap in a pre-resolved one so\n * `getWorker()` sees the new worker instance immediately.\n */\n this.#workerResolvers = Promise.withResolvers()\n this.#workerResolvers.resolve([worker, registration])\n this.workerPromise = this.#workerResolvers.promise\n }\n\n this.#channel.on('REQUEST', this.#handleRequest.bind(this))\n this.#channel.on('RESPONSE', this.#handleResponse.bind(this))\n this.#channel.on('REQUEST_ERROR', this.#handleRequestError.bind(this))\n\n window.addEventListener(\n 'pagehide',\n (event) => {\n if (event.persisted) {\n return\n }\n\n if (worker.state !== 'redundant') {\n this.#channel.postMessage('CLIENT_CLOSE')\n }\n\n clearInterval(this.#keepAliveInterval)\n\n window.postMessage({ type: 'msw/worker:stop' })\n },\n {\n signal: this.#listenerController?.signal,\n },\n )\n\n await this.#checkWorkerIntegrity().catch((error) => {\n devUtils.error(\n 'Error while checking the worker script integrity. Please report this on GitHub (https://github.com/mswjs/msw/issues) and include the original error below.',\n )\n console.error(error)\n })\n\n this.#keepAliveInterval = window.setInterval(() => {\n this.#channel.postMessage('KEEPALIVE_REQUEST')\n }, 5000)\n\n if (!this.#context?.quiet) {\n validateWorkerScope(registration)\n }\n\n return [worker, registration] as const\n }\n\n async #handleRequest(event: WorkerChannelRequestEvent): Promise<void> {\n const request = deserializeRequest(event.data)\n RequestHandler.cache.set(request, request.clone())\n\n const frame = new ServiceWorkerHttpNetworkFrame({\n event,\n request,\n })\n this.#frames.set(event.data.id, frame)\n\n await this.queue(frame)\n }\n\n async #handleResponse(event: WorkerChannelResponseEvent): Promise<void> {\n const { request, response, isMockedResponse } = event.data\n const frame = this.#frames.get(request.id)\n\n /**\n * CORS requests with `mode: \"no-cors\"` result in \"opaque\" responses.\n * That kind of responses cannot be manipulated in JavaScript due\n * to the security considerations.\n * @see https://fetch.spec.whatwg.org/#concept-filtered-response-opaque\n * @see https://github.com/mswjs/msw/issues/529\n */\n if (response.type?.includes('opaque')) {\n this.#frames.delete(request.id)\n frame?.events.removeAllListeners()\n return\n }\n\n this.#frames.delete(request.id)\n\n /**\n * @note A request frame will be missing in case of passthrough after the worker is stopped.\n * Creating a frame is costly so it's better to handle it as an edge case here.\n */\n if (frame == null) {\n return\n }\n\n const fetchRequest = deserializeRequest(request)\n const fetchResponse =\n response.status === 0\n ? Response.error()\n : new FetchResponse(\n /**\n * Responses may be streams here, but when we create a response object\n * with null-body status codes, like 204, 205, 304 Response will\n * throw when passed a non-null body, so ensure it's null here\n * for those codes\n */\n FetchResponse.isResponseWithBody(response.status)\n ? response.body\n : null,\n {\n ...response,\n /**\n * Set response URL if it's not set already.\n * @see https://github.com/mswjs/msw/issues/2030\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/url\n */\n url: request.url,\n },\n )\n\n try {\n frame.events.emit(\n new ResponseEvent(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n requestId: frame.data.id,\n request: fetchRequest,\n response: fetchResponse,\n isMockedResponse,\n },\n ),\n )\n } finally {\n frame.events.removeAllListeners()\n }\n }\n\n /**\n * @note A request can settle without ever producing a response\n * (e.g. a passthrough request failing with a network error).\n * The worker never sends the \"RESPONSE\" message for such requests,\n * so the frame must be released here to prevent it from being retained.\n * No \"response:*\" event is emitted, consistent with the Node.js source.\n * @see https://github.com/mswjs/msw/issues/2792\n */\n #handleRequestError(event: WorkerChannelRequestErrorEvent): void {\n const { request } = event.data\n const frame = this.#frames.get(request.id)\n this.#frames.delete(request.id)\n frame?.events.removeAllListeners()\n }\n\n #defaultFindWorker: FindWorker = (workerUrl, mockServiceWorkerUrl) => {\n return workerUrl === mockServiceWorkerUrl\n }\n\n async #checkWorkerIntegrity(): Promise<void> {\n const integrityCheckPromise = Promise.withResolvers<void>()\n\n this.#channel.postMessage('INTEGRITY_CHECK_REQUEST')\n this.#channel.once('INTEGRITY_CHECK_RESPONSE', (event) => {\n const { checksum, packageVersion } = event.data\n\n // Compare the response from the Service Worker and the\n // global variable set during the build.\n\n // The integrity is validated based on the worker script's checksum\n // that's derived from its minified content during the build.\n // The \"SERVICE_WORKER_CHECKSUM\" global variable is injected by the build.\n if (checksum !== SERVICE_WORKER_CHECKSUM) {\n devUtils.warn(\n `The currently registered Service Worker has been generated by a different version of MSW (${packageVersion}) and may not be fully compatible with the installed version.\n\nIt's recommended you update your worker script by running this command:\n\n \\u2022 npx msw init <PUBLIC_DIR>\n\nYou can also automate this process and make the worker script update automatically upon the library installations. Read more: https://mswjs.io/docs/cli/init.`,\n )\n }\n\n integrityCheckPromise.resolve()\n })\n\n return integrityCheckPromise.promise\n }\n\n async #printStartMessage() {\n if (this.#workerState === 'rejected') {\n return\n }\n\n invariant(\n this.#clientPromise != null,\n '[ServiceWorkerSource] Failed to print a start message: client confirmation not received',\n )\n\n const client = await this.#clientPromise\n const [worker, registration] = await this.workerPromise\n\n console.groupCollapsed(\n `%c${devUtils.formatMessage('Mocking enabled.')}`,\n 'color:orangered;font-weight:bold;',\n )\n // eslint-disable-next-line no-console\n console.log(\n '%cDocumentation: %chttps://mswjs.io/docs',\n 'font-weight:bold',\n 'font-weight:normal',\n )\n // eslint-disable-next-line no-console\n console.log('Found an issue? https://github.com/mswjs/msw/issues')\n\n // eslint-disable-next-line no-console\n console.log('Worker script URL:', worker.scriptURL)\n\n // eslint-disable-next-line no-console\n console.log('Worker scope:', registration.scope)\n\n if (client) {\n // eslint-disable-next-line no-console\n console.log('Client ID: %s (%s)', client.id, client.frameType)\n }\n\n console.groupEnd()\n }\n\n #printStopMessage(): void {\n // eslint-disable-next-line no-console\n console.log(\n `%c${devUtils.formatMessage('Mocking disabled.')}`,\n 'color:orangered;font-weight:bold;',\n )\n }\n}\n\nclass ServiceWorkerHttpNetworkFrame extends HttpNetworkFrame {\n #event: WorkerChannelRequestEvent\n\n constructor(options: { event: WorkerChannelRequestEvent; request: Request }) {\n super({ request: options.request })\n this.#event = options.event\n }\n\n public passthrough(): void {\n // Forward the request headers so that any modifications made\n // in the request handlers are applied to the passthrough request.\n this.#event.postMessage('PASSTHROUGH', {\n request: {\n headers: Array.from(this.data.request.headers),\n },\n })\n }\n\n public respondWith(response?: Response): void {\n if (response) {\n this.#respondWith(response)\n }\n }\n\n public errorWith(reason?: unknown): void {\n if (reason instanceof Response) {\n return this.respondWith(reason)\n }\n\n devUtils.warn(\n `Uncaught exception in the request handler for \"%s %s\". This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/http/mocking-responses/error-responses`,\n this.data.request.method,\n this.data.request.url,\n )\n\n const error =\n reason instanceof Error\n ? reason\n : new Error(reason?.toString() || 'Request failure')\n\n // Treat exceptions during the request handling as 500 responses.\n // This should alert the developer that there's a problem.\n this.respondWith(\n HttpResponse.json(\n {\n name: error.name,\n message: error.message,\n stack: error.stack,\n },\n {\n status: 500,\n statusText: 'Request Handler Error',\n },\n ),\n )\n }\n\n async #respondWith(response: Response): Promise<void> {\n let responseBody: ReadableStream<Uint8Array> | ArrayBuffer | null\n let transfer: [ReadableStream<Uint8Array>] | undefined\n const responseInit = toResponseInit(response)\n\n if (supportsReadableStreamTransfer()) {\n responseBody = response.body\n transfer = response.body == null ? undefined : [response.body]\n } else {\n responseBody =\n response.body == null ? null : await response.clone().arrayBuffer()\n }\n\n this.#event.postMessage(\n 'MOCK_RESPONSE',\n {\n ...responseInit,\n body: responseBody,\n },\n transfer,\n )\n }\n}\n","import { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { InterceptorSource } from '#core/experimental/sources/interceptor-source'\nimport type { NetworkFrameResolutionContext } from '#core/experimental/frames/network-frame'\nimport { devUtils } from '#core/utils/internal/dev-utils'\n\nexport class FallbackHttpSource extends InterceptorSource {\n /**\n * The resolved context of the network this source was last enabled with.\n */\n #context?: NetworkFrameResolutionContext\n\n constructor() {\n super({\n interceptors: [new XMLHttpRequestInterceptor(), new FetchInterceptor()],\n })\n }\n\n public enable(context?: NetworkFrameResolutionContext): void {\n this.#context = context\n super.enable()\n\n if (!this.#context?.quiet) {\n this.#printStartMessage()\n }\n }\n\n public disable(): void {\n super.disable()\n\n if (!this.#context?.quiet) {\n this.#printStopMessage()\n }\n }\n\n #printStartMessage(): void {\n console.groupCollapsed(\n `%c${devUtils.formatMessage('Mocking enabled (fallback mode).')}`,\n 'color:orangered;font-weight:bold;',\n )\n // eslint-disable-next-line no-console\n console.log(\n '%cDocumentation: %chttps://mswjs.io/docs',\n 'font-weight:bold',\n 'font-weight:normal',\n )\n // eslint-disable-next-line no-console\n console.log('Found an issue? https://github.com/mswjs/msw/issues')\n console.groupEnd()\n }\n\n #printStopMessage(): void {\n // eslint-disable-next-line no-console\n console.log(\n `%c${devUtils.formatMessage('Mocking disabled.')}`,\n 'color:orangered;font-weight:bold;',\n )\n }\n}\n","import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'\nimport {\n defineNetwork,\n NetworkReadyState,\n} from '#core/experimental/define-network'\nimport type { AnyHandler } from '#core/experimental/handlers-controller'\nimport { InterceptorSource } from '#core/experimental/sources/interceptor-source'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport { supportsServiceWorker } from './utils/supports'\nimport { ServiceWorkerSource } from './sources/service-worker-source'\nimport { FallbackHttpSource } from './sources/fallback-http-source'\nimport type { SetupWorker } from './glossary'\n\nconst DEFAULT_WORKER_URL = '/mockServiceWorker.js'\n\n/**\n * Sets up a requests interception in the browser with the given request handlers.\n * @param {Array<AnyHandler>} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-worker `setupWorker()` API reference}\n */\nexport function setupWorker(...handlers: Array<AnyHandler>): SetupWorker {\n invariant(\n !isNodeProcess(),\n devUtils.formatMessage(\n 'Failed to execute `setupWorker` in a non-browser environment',\n ),\n )\n\n const network = defineNetwork<\n Array<ServiceWorkerSource | FallbackHttpSource | InterceptorSource>\n >({\n sources: [],\n handlers,\n })\n\n return {\n get readyState() {\n return network.readyState\n },\n async start(options) {\n invariant(\n network.readyState === NetworkReadyState.DISABLED,\n devUtils.formatMessage(\n 'Failed to call \"worker.start()\": the worker is already started. Remove the redundant \"worker.start()\" call.',\n ),\n )\n\n const httpSource = supportsServiceWorker()\n ? await ServiceWorkerSource.from({\n serviceWorker: {\n url:\n options?.serviceWorker?.url?.toString() || DEFAULT_WORKER_URL,\n options: options?.serviceWorker?.options,\n },\n findWorker: options?.findWorker,\n })\n : new FallbackHttpSource()\n\n network.configure({\n sources: [\n httpSource,\n new InterceptorSource({\n interceptors: [new WebSocketInterceptor()],\n }),\n ],\n onUnhandledFrame: options?.onUnhandledFrame ?? 'warn',\n context: {\n quiet: options?.quiet,\n },\n })\n\n await network.enable()\n\n if (httpSource instanceof ServiceWorkerSource) {\n const [, registration] = await httpSource.workerPromise\n return registration\n }\n },\n async stop() {\n await network.disable()\n window.postMessage({ type: 'msw/worker:stop' })\n },\n events: network.events,\n use: network.use.bind(network),\n resetHandlers: network.resetHandlers.bind(network),\n restoreHandlers: network.restoreHandlers.bind(network),\n listHandlers: network.listHandlers.bind(network),\n }\n}\n","import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'\nimport type { DefineNetworkOptions } from '#core/experimental/define-network'\nimport {\n InterceptorSource,\n type InterceptorSourceOptions,\n} from '#core/experimental/sources/interceptor-source'\nimport { ServiceWorkerSource } from './sources/service-worker-source'\nimport { FallbackHttpSource } from './sources/fallback-http-source'\nimport { supportsServiceWorker } from './utils/supports'\n\nexport function createDefaultNetworkOptions(\n workerUrl = '/mockServiceWorker.js',\n): DefineNetworkOptions<\n [ServiceWorkerSource | FallbackHttpSource, InterceptorSource]\n> {\n return {\n sources: [\n supportsServiceWorker()\n ? new ServiceWorkerSource({ serviceWorker: { url: workerUrl } })\n : new FallbackHttpSource(),\n new InterceptorSource({\n interceptors: [\n new WebSocketInterceptor() as InterceptorSourceOptions['interceptors'][number],\n ],\n }),\n ],\n onUnhandledFrame: 'warn',\n }\n}\n\nexport const defaultNetworkOptions = createDefaultNetworkOptions()\n"],"mappings":"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"}
@@ -286,10 +286,18 @@ declare class GraphQLSubscriptionTransportHandler extends GraphQLWebSocketHandle
286
286
  subscriptionId: string;
287
287
  }): void;
288
288
  /**
289
- * Drop this transport's subscribers and active subscriptions from the
290
- * sessions it participates in. The sessions themselves are left intact:
291
- * they are shared with the other transports of the same connection and
292
- * own the protocol listeners for as long as the client stays connected.
289
+ * Remove the given handler from the subscribers of every session
290
+ * this transport participates in. The handler no longer matches
291
+ * subscriptions on the connections opened while it was registered.
292
+ */
293
+ unsubscribe(handler: WebSocketHandler): void;
294
+ /**
295
+ * End the active subscriptions of the sessions this transport
296
+ * participates in. The sessions and their subscribers are left intact:
297
+ * the handlers that survive the reset keep serving the connections
298
+ * opened before it, while the removed handlers unsubscribe themselves
299
+ * on disposal. The sessions own the protocol listeners for as long as
300
+ * the client stays connected.
293
301
  *
294
302
  * @note This method is invoked automatically when the handlers
295
303
  * controller resets the handlers (e.g. `server.resetHandlers()`).
@@ -368,6 +376,13 @@ export declare class GraphQLSubscriptionHandler<Query extends GraphQLQuery = Gra
368
376
  options?: GraphQLSubscriptionHandlerOptions;
369
377
  });
370
378
  reset(): void;
379
+ /**
380
+ * Stop serving the connections this handler was bound to.
381
+ * @note This method is invoked automatically when the handler
382
+ * is removed from the network, either by resetting the handlers
383
+ * (e.g. `server.resetHandlers()`) or by disabling the network.
384
+ */
385
+ dispose(): void;
371
386
  /**
372
387
  * @note Individual subscription handlers stay silent. The subscription
373
388
  * transport owns the GraphQL-aware logging for the entire connection
@@ -658,23 +658,26 @@ var GraphQLSubscriptionTransportHandler = class extends GraphQLWebSocketHandler
658
658
  this.#endSubscription(connection, args.subscriptionId);
659
659
  }
660
660
  /**
661
- * Drop this transport's subscribers and active subscriptions from the
662
- * sessions it participates in. The sessions themselves are left intact:
663
- * they are shared with the other transports of the same connection and
664
- * own the protocol listeners for as long as the client stays connected.
661
+ * Remove the given handler from the subscribers of every session
662
+ * this transport participates in. The handler no longer matches
663
+ * subscriptions on the connections opened while it was registered.
664
+ */
665
+ unsubscribe(handler) {
666
+ for (const connection of connections.values()) connection.subscribers.delete(handler);
667
+ }
668
+ /**
669
+ * End the active subscriptions of the sessions this transport
670
+ * participates in. The sessions and their subscribers are left intact:
671
+ * the handlers that survive the reset keep serving the connections
672
+ * opened before it, while the removed handlers unsubscribe themselves
673
+ * on disposal. The sessions own the protocol listeners for as long as
674
+ * the client stays connected.
665
675
  *
666
676
  * @note This method is invoked automatically when the handlers
667
677
  * controller resets the handlers (e.g. `server.resetHandlers()`).
668
678
  */
669
679
  reset() {
670
- for (const connection of connections.values()) {
671
- let ownsConnection = false;
672
- for (const [handler, entry] of connection.subscribers) if (entry.transport === this) {
673
- connection.subscribers.delete(handler);
674
- ownsConnection = true;
675
- }
676
- if (ownsConnection) this.#endAllSubscriptions(connection);
677
- }
680
+ for (const connection of connections.values()) if (Array.from(connection.subscribers.values()).some((entry) => entry.transport === this)) this.#endAllSubscriptions(connection);
678
681
  }
679
682
  /**
680
683
  * Forget the sessions of this transport, ending their subscriptions.
@@ -820,6 +823,15 @@ var GraphQLSubscriptionHandler = class extends GraphQLWebSocketHandler {
820
823
  this.isUsed = false;
821
824
  }
822
825
  /**
826
+ * Stop serving the connections this handler was bound to.
827
+ * @note This method is invoked automatically when the handler
828
+ * is removed from the network, either by resetting the handlers
829
+ * (e.g. `server.resetHandlers()`) or by disabling the network.
830
+ */
831
+ dispose() {
832
+ this.#transport.unsubscribe(this);
833
+ }
834
+ /**
823
835
  * @note Individual subscription handlers stay silent. The subscription
824
836
  * transport owns the GraphQL-aware logging for the entire connection
825
837
  * (a logger is attached once per matching handler otherwise).