@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.
- package/README.md +5 -4
- package/changes.json +7 -3
- package/lib/_chunks/cookie-store.js +3 -2
- package/lib/_chunks/cookie-store.js.map +1 -1
- package/lib/_chunks/interceptor-source.d.ts +5 -1
- package/lib/_chunks/interceptor-source.js +18 -5
- package/lib/_chunks/interceptor-source.js.map +1 -1
- package/lib/_chunks/request-handler.d.ts +3 -2
- package/lib/browser/index.d.ts +4 -9
- package/lib/browser/index.js +21 -14
- package/lib/browser/index.js.map +1 -1
- package/lib/graphql/index.d.ts +19 -4
- package/lib/graphql/index.js +24 -12
- package/lib/graphql/index.js.map +1 -1
- package/lib/iife/index.js +66 -33
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/lib/vite/index.js +10 -7
- package/lib/vite/index.js.map +1 -1
- package/lib/vite/runtime.d.ts +2 -3
- package/lib/vite/runtime.js +70 -68
- package/lib/vite/runtime.js.map +1 -1
- package/package.json +12 -9
- package/src/browser/default-network-options.ts +1 -1
- package/src/browser/setup-worker.ts +1 -4
- package/src/browser/sources/fallback-http-source.ts +11 -8
- package/src/browser/sources/service-worker-source.ts +12 -5
- package/src/browser/utils/should-invalidate-worker.test.ts +0 -16
- package/src/core/experimental/define-network.ts +1 -1
- package/src/core/experimental/handlers-controller.test.ts +61 -0
- package/src/core/experimental/handlers-controller.ts +39 -6
- package/src/core/experimental/sources/network-source.ts +8 -1
- package/src/core/handlers/handler.ts +3 -2
- package/src/graphql/graphql-subscription.ts +30 -12
- package/src/vite/plugin.test.ts +1 -1
- package/src/vite/plugin.ts +13 -10
- package/src/vite/runtime.ts +85 -85
- package/src/vite/tsconfig.build.json +1 -1
- package/src/vite/options.d.ts +0 -5
package/lib/browser/index.js
CHANGED
|
@@ -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.#
|
|
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.#
|
|
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.#
|
|
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
|
-
|
|
499
|
-
|
|
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
|
|
513
|
+
if (!this.#context?.quiet) this.#printStartMessage();
|
|
506
514
|
}
|
|
507
515
|
disable() {
|
|
508
516
|
super.disable();
|
|
509
|
-
if (!this
|
|
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
|
-
|
|
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(
|
|
583
|
+
sources: [supportsServiceWorker() ? new ServiceWorkerSource({ serviceWorker: { url: workerUrl } }) : new FallbackHttpSource(), new InterceptorSource({ interceptors: [new WebSocketInterceptor()] })],
|
|
577
584
|
onUnhandledFrame: "warn"
|
|
578
585
|
};
|
|
579
586
|
}
|
package/lib/browser/index.js.map
CHANGED
|
@@ -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":"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"}
|
|
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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"}
|
package/lib/graphql/index.d.ts
CHANGED
|
@@ -286,10 +286,18 @@ declare class GraphQLSubscriptionTransportHandler extends GraphQLWebSocketHandle
|
|
|
286
286
|
subscriptionId: string;
|
|
287
287
|
}): void;
|
|
288
288
|
/**
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
|
|
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
|
package/lib/graphql/index.js
CHANGED
|
@@ -658,23 +658,26 @@ var GraphQLSubscriptionTransportHandler = class extends GraphQLWebSocketHandler
|
|
|
658
658
|
this.#endSubscription(connection, args.subscriptionId);
|
|
659
659
|
}
|
|
660
660
|
/**
|
|
661
|
-
*
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
|
|
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).
|