UNPKG

msw

Version:

Seamless REST/GraphQL API mocking library for browser and Node.js.

1 lines 220 kB
{"version":3,"sources":["../../node_modules/.pnpm/outvariant@1.4.3/node_modules/outvariant/src/format.ts","../../node_modules/.pnpm/outvariant@1.4.3/node_modules/outvariant/src/invariant.ts","../../node_modules/.pnpm/is-node-process@1.2.0/node_modules/is-node-process/src/index.ts","../../src/browser/setupWorker/start/utils/prepareStartHandler.ts","../../src/browser/setupWorker/start/createStartHandler.ts","../../node_modules/.pnpm/@open-draft+until@2.1.0/node_modules/@open-draft/until/src/until.ts","../../src/browser/setupWorker/start/utils/getWorkerInstance.ts","../../src/browser/utils/getAbsoluteWorkerUrl.ts","../../src/browser/setupWorker/start/utils/getWorkerByRegistration.ts","../../node_modules/.pnpm/@open-draft+deferred-promise@2.2.0/node_modules/@open-draft/deferred-promise/src/createDeferredExecutor.ts","../../node_modules/.pnpm/@open-draft+deferred-promise@2.2.0/node_modules/@open-draft/deferred-promise/src/DeferredPromise.ts","../../src/browser/setupWorker/start/utils/printStartMessage.ts","../../src/browser/setupWorker/start/utils/enableMocking.ts","../../src/browser/utils/pruneGetRequestBody.ts","../../src/browser/utils/deserializeRequest.ts","../../src/browser/setupWorker/start/createRequestListener.ts","../../src/browser/utils/checkWorkerIntegrity.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/bufferUtils.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/glossary.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/canParseUrl.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/getValueBySymbol.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/fetchUtils.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/getRawRequest.ts","../../node_modules/.pnpm/@open-draft+logger@0.3.0/node_modules/@open-draft/logger/lib/index.mjs","../../node_modules/.pnpm/strict-event-emitter@0.5.1/node_modules/strict-event-emitter/src/MemoryLeakError.ts","../../node_modules/.pnpm/strict-event-emitter@0.5.1/node_modules/strict-event-emitter/src/Emitter.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/Interceptor.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/createRequestId.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/BatchInterceptor.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/getCleanUrl.ts","../../src/browser/setupWorker/start/createResponseListener.ts","../../src/browser/setupWorker/start/utils/validateWorkerScope.ts","../../src/browser/setupWorker/setupWorker.ts","../../src/browser/utils/supportsReadableStreamTransfer.ts","../../node_modules/.pnpm/rettime@0.7.0/node_modules/rettime/src/index.ts","../../src/browser/utils/workerChannel.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/RequestController.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/InterceptorError.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/emitAsync.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/handleRequest.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/isObject.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/isPropertyAccessible.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/responseUtils.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/isNodeLikeError.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/hasConfigurableGlobal.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/createNetworkError.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/followRedirect.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/brotli-decompress.browser.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/decompression.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/index.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createEvent.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/findPropertySource.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/createProxy.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/utils/parseJson.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createResponse.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts","../../node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts","../../src/browser/setupWorker/start/createFallbackRequestListener.ts","../../src/browser/setupWorker/stop/utils/printStopMessage.ts"],"sourcesContent":["const POSITIONALS_EXP = /(%?)(%([sdijo]))/g\n\nfunction serializePositional(positional: any, flag: string): any {\n switch (flag) {\n // Strings.\n case 's':\n return positional\n\n // Digits.\n case 'd':\n case 'i':\n return Number(positional)\n\n // JSON.\n case 'j':\n return JSON.stringify(positional)\n\n // Objects.\n case 'o': {\n // Preserve stings to prevent extra quotes around them.\n if (typeof positional === 'string') {\n return positional\n }\n\n const json = JSON.stringify(positional)\n\n // If the positional isn't serializable, return it as-is.\n if (json === '{}' || json === '[]' || /^\\[object .+?\\]$/.test(json)) {\n return positional\n }\n\n return json\n }\n }\n}\n\nexport function format(message: string, ...positionals: any[]): string {\n if (positionals.length === 0) {\n return message\n }\n\n let positionalIndex = 0\n let formattedMessage = message.replace(\n POSITIONALS_EXP,\n (match, isEscaped, _, flag) => {\n const positional = positionals[positionalIndex]\n const value = serializePositional(positional, flag)\n\n if (!isEscaped) {\n positionalIndex++\n return value\n }\n\n return match\n }\n )\n\n // Append unresolved positionals to string as-is.\n if (positionalIndex < positionals.length) {\n formattedMessage += ` ${positionals.slice(positionalIndex).join(' ')}`\n }\n\n formattedMessage = formattedMessage.replace(/%{2,2}/g, '%')\n\n return formattedMessage\n}\n","import { format } from './format'\n\nconst STACK_FRAMES_TO_IGNORE = 2\n\n/**\n * Remove the \"outvariant\" package trace from the given error.\n * This scopes down the error stack to the relevant parts\n * when used in other applications.\n */\nfunction cleanErrorStack(error: Error): void {\n if (!error.stack) {\n return\n }\n\n const nextStack = error.stack.split('\\n')\n nextStack.splice(1, STACK_FRAMES_TO_IGNORE)\n error.stack = nextStack.join('\\n')\n}\n\nexport class InvariantError extends Error {\n name = 'Invariant Violation'\n\n constructor(public readonly message: string, ...positionals: any[]) {\n super(message)\n this.message = format(message, ...positionals)\n cleanErrorStack(this)\n }\n}\n\nexport interface CustomErrorConstructor {\n new (message: string): Error\n}\n\nexport interface CustomErrorFactory {\n (message: string): Error\n}\n\nexport type CustomError = CustomErrorConstructor | CustomErrorFactory\n\ntype Invariant = {\n (\n predicate: unknown,\n message: string,\n ...positionals: any[]\n ): asserts predicate\n\n as(\n ErrorConstructor: CustomError,\n predicate: unknown,\n message: string,\n ...positionals: unknown[]\n ): asserts predicate\n}\n\nexport const invariant: Invariant = (\n predicate,\n message,\n ...positionals\n): asserts predicate => {\n if (!predicate) {\n throw new InvariantError(message, ...positionals)\n }\n}\n\ninvariant.as = (ErrorConstructor, predicate, message, ...positionals) => {\n if (!predicate) {\n const formatMessage =\n positionals.length === 0 ? message : format(message, ...positionals)\n let error: Error\n\n try {\n error = Reflect.construct(ErrorConstructor as CustomErrorConstructor, [\n formatMessage,\n ])\n } catch (err) {\n error = (ErrorConstructor as CustomErrorFactory)(formatMessage)\n }\n\n throw error\n }\n}\n","/**\n * Determines if the current process is a Node.js process.\n */\nexport function isNodeProcess(): boolean {\n if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {\n return true\n }\n\n if (typeof process !== 'undefined') {\n // Electron (https://www.electronjs.org/docs/latest/api/process#processtype-readonly)\n const type = (process as any).type\n if (type === 'renderer' || type === 'worker') {\n return false\n }\n\n\n return !!(\n process.versions &&\n process.versions.node\n )\n }\n\n return false\n}\n","import { RequiredDeep } from '~/core/typeUtils'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport {\n SetupWorker,\n SetupWorkerInternalContext,\n StartHandler,\n StartOptions,\n} from '../../glossary'\n\nexport const DEFAULT_START_OPTIONS: RequiredDeep<StartOptions> = {\n serviceWorker: {\n url: '/mockServiceWorker.js',\n options: null as any,\n },\n quiet: false,\n waitUntilReady: true,\n onUnhandledRequest: 'warn',\n findWorker(scriptURL, mockServiceWorkerUrl) {\n return scriptURL === mockServiceWorkerUrl\n },\n}\n\n/**\n * Returns resolved worker start options, merging the default options\n * with the given custom options.\n */\nexport function resolveStartOptions(\n initialOptions?: StartOptions,\n): RequiredDeep<StartOptions> {\n return mergeRight(\n DEFAULT_START_OPTIONS,\n initialOptions || {},\n ) as RequiredDeep<StartOptions>\n}\n\nexport function prepareStartHandler(\n handler: StartHandler,\n context: SetupWorkerInternalContext,\n): SetupWorker['start'] {\n return (initialOptions) => {\n context.startOptions = resolveStartOptions(initialOptions)\n return handler(context.startOptions, initialOptions || {})\n }\n}\n","import { devUtils } from '~/core/utils/internal/devUtils'\nimport { getWorkerInstance } from './utils/getWorkerInstance'\nimport { enableMocking } from './utils/enableMocking'\nimport type { SetupWorkerInternalContext, StartHandler } from '../glossary'\nimport { createRequestListener } from './createRequestListener'\nimport { checkWorkerIntegrity } from '../../utils/checkWorkerIntegrity'\nimport { createResponseListener } from './createResponseListener'\nimport { validateWorkerScope } from './utils/validateWorkerScope'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\n\nexport const createStartHandler = (\n context: SetupWorkerInternalContext,\n): StartHandler => {\n return function start(options, customOptions) {\n const startWorkerInstance = async () => {\n // Remove all previously existing event listeners.\n // This way none of the listeners persists between Fast refresh\n // of the application's code.\n context.workerChannel.removeAllListeners()\n\n // Handle requests signaled by the worker.\n context.workerChannel.on(\n 'REQUEST',\n createRequestListener(context, options),\n )\n\n // Handle responses signaled by the worker.\n context.workerChannel.on('RESPONSE', createResponseListener(context))\n\n const instance = await getWorkerInstance(\n options.serviceWorker.url,\n options.serviceWorker.options,\n options.findWorker,\n )\n\n const [worker, registration] = instance\n\n if (!worker) {\n const missingWorkerMessage = customOptions?.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 options.serviceWorker.url,\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 options.serviceWorker.url,\n location.host,\n )\n\n throw new Error(missingWorkerMessage)\n }\n\n context.workerPromise.resolve(worker)\n context.registration = registration\n\n window.addEventListener('beforeunload', () => {\n if (worker.state !== 'redundant') {\n // Notify the Service Worker that this client has closed.\n // Internally, it's similar to disabling the mocking, only\n // client close event has a handler that self-terminates\n // the Service Worker when there are no open clients.\n context.workerChannel.postMessage('CLIENT_CLOSED')\n }\n\n // Make sure we're always clearing the interval - there are reports that not doing this can\n // cause memory leaks in headless browser environments.\n window.clearInterval(context.keepAliveInterval)\n\n // Notify others about this client disconnecting.\n // E.g. this will purge the in-memory WebSocket clients since\n // starting the worker again will assign them new IDs.\n window.postMessage({ type: 'msw/worker:stop' })\n })\n\n // Check if the active Service Worker has been generated\n // by the currently installed version of MSW.\n await checkWorkerIntegrity(context).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 context.keepAliveInterval = window.setInterval(\n () => context.workerChannel.postMessage('KEEPALIVE_REQUEST'),\n 5000,\n )\n\n // Warn the user when loading the page that lies outside\n // of the worker's scope.\n validateWorkerScope(registration, context.startOptions)\n\n return registration\n }\n\n const workerRegistration = startWorkerInstance().then(\n async (registration) => {\n const pendingInstance = registration.installing || registration.waiting\n\n if (pendingInstance) {\n const activationPromise = new DeferredPromise<void>()\n\n pendingInstance.addEventListener('statechange', () => {\n if (pendingInstance.state === 'activated') {\n activationPromise.resolve()\n }\n })\n\n // Wait until the worker is activated.\n // Assume the worker is already activated if there's no pending registration\n // (i.e. when reloading the page after a successful activation).\n await activationPromise\n }\n\n // Print the activation message only after the worker has been activated.\n await enableMocking(context, options).catch((error) => {\n devUtils.error(\n 'Failed to enable mocking. Please report this on GitHub (https://github.com/mswjs/msw/issues) and include the original error below.',\n )\n throw error\n })\n\n return registration\n },\n )\n\n return workerRegistration\n }\n}\n","export type AsyncTuple<\n ErrorType extends any = Error,\n DataType extends any = unknown,\n> =\n | {\n error: ErrorType\n data: null\n }\n | { error: null; data: DataType }\n\n/**\n * Gracefully handles a given Promise factory.\n * @example\n * const { error, data } = await until(() => asyncAction())\n */\nexport const until = async <\n ErrorType extends any = Error,\n DataType extends any = unknown,\n>(\n promise: () => Promise<DataType>,\n): Promise<AsyncTuple<ErrorType, DataType>> => {\n try {\n const data = await promise().catch((error) => {\n throw error\n })\n return { error: null, data }\n } catch (error) {\n return { error, data: null }\n }\n}\n","import { until } from '@open-draft/until'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport { getAbsoluteWorkerUrl } from '../../../utils/getAbsoluteWorkerUrl'\nimport { getWorkerByRegistration } from './getWorkerByRegistration'\nimport { 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 registrationResult = await until<Error, 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\n // Handle Service Worker registration errors.\n if (registrationResult.error) {\n const isWorkerMissing = registrationResult.error.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 registrationResult.error.message,\n ),\n )\n }\n\n return registrationResult.data\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 { 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 const relevantStates = allStates.filter((state): state is ServiceWorker => {\n return state != null\n })\n const worker = relevantStates.find((worker) => {\n return findWorker(worker.scriptURL, absoluteWorkerUrl)\n })\n\n return worker || null\n}\n","export type PromiseState = 'pending' | 'fulfilled' | 'rejected'\n\nexport type Executor<Value> = ConstructorParameters<typeof Promise<Value>>[0]\nexport type ResolveFunction<Value> = Parameters<Executor<Value>>[0]\nexport type RejectFunction<Reason> = Parameters<Executor<Reason>>[1]\n\nexport type DeferredPromiseExecutor<Input = never, Output = Input> = {\n (resolve?: ResolveFunction<Input>, reject?: RejectFunction<any>): void\n\n resolve: ResolveFunction<Input>\n reject: RejectFunction<any>\n result?: Output\n state: PromiseState\n rejectionReason?: unknown\n}\nexport function createDeferredExecutor<\n Input = never,\n Output = Input\n>(): DeferredPromiseExecutor<Input, Output> {\n const executor = <DeferredPromiseExecutor<Input, Output>>((\n resolve,\n reject\n ) => {\n executor.state = 'pending'\n\n executor.resolve = (data) => {\n if (executor.state !== 'pending') {\n return\n }\n\n executor.result = data as Output\n\n const onFulfilled = <Value>(value: Value) => {\n executor.state = 'fulfilled'\n return value\n }\n\n return resolve(\n data instanceof Promise ? data : Promise.resolve(data).then(onFulfilled)\n )\n }\n\n executor.reject = (reason) => {\n if (executor.state !== 'pending') {\n return\n }\n\n queueMicrotask(() => {\n executor.state = 'rejected'\n })\n\n return reject((executor.rejectionReason = reason))\n }\n })\n\n return executor\n}\n","import {\n type Executor,\n type RejectFunction,\n type ResolveFunction,\n type DeferredPromiseExecutor,\n createDeferredExecutor,\n} from './createDeferredExecutor'\n\nexport class DeferredPromise<Input, Output = Input> extends Promise<Input> {\n #executor: DeferredPromiseExecutor\n\n public resolve: ResolveFunction<Output>\n public reject: RejectFunction<Output>\n\n constructor(executor: Executor<Input> | null = null) {\n const deferredExecutor = createDeferredExecutor()\n super((originalResolve, originalReject) => {\n deferredExecutor(originalResolve, originalReject)\n executor?.(deferredExecutor.resolve, deferredExecutor.reject)\n })\n\n this.#executor = deferredExecutor\n this.resolve = this.#executor.resolve\n this.reject = this.#executor.reject\n }\n\n public get state() {\n return this.#executor.state\n }\n\n public get rejectionReason() {\n return this.#executor.rejectionReason\n }\n\n public then<ThenResult = Input, CatchResult = never>(\n onFulfilled?: (value: Input) => ThenResult | PromiseLike<ThenResult>,\n onRejected?: (reason: any) => CatchResult | PromiseLike<CatchResult>\n ) {\n return this.#decorate(super.then(onFulfilled, onRejected))\n }\n\n public catch<CatchResult = never>(\n onRejected?: (reason: any) => CatchResult | PromiseLike<CatchResult>\n ) {\n return this.#decorate(super.catch(onRejected))\n }\n\n public finally(onfinally?: () => void | Promise<any>) {\n return this.#decorate(super.finally(onfinally))\n }\n\n #decorate<ChildInput>(\n promise: Promise<ChildInput>\n ): DeferredPromise<ChildInput, Output> {\n return Object.defineProperties(promise, {\n resolve: { configurable: true, value: this.resolve },\n reject: { configurable: true, value: this.reject },\n }) as DeferredPromise<ChildInput, Output>\n }\n}\n","import type { ServiceWorkerIncomingEventsMap } from '../../glossary'\nimport { devUtils } from '~/core/utils/internal/devUtils'\n\ninterface PrintStartMessageArgs {\n quiet?: boolean\n message?: string\n workerUrl?: string\n workerScope?: string\n client?: ServiceWorkerIncomingEventsMap['MOCKING_ENABLED']['client']\n}\n\n/**\n * Prints a worker activation message in the browser's console.\n */\nexport function printStartMessage(args: PrintStartMessageArgs = {}) {\n if (args.quiet) {\n return\n }\n\n const message = args.message || 'Mocking enabled.'\n\n console.groupCollapsed(\n `%c${devUtils.formatMessage(message)}`,\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 if (args.workerUrl) {\n // eslint-disable-next-line no-console\n console.log('Worker script URL:', args.workerUrl)\n }\n\n if (args.workerScope) {\n // eslint-disable-next-line no-console\n console.log('Worker scope:', args.workerScope)\n }\n\n if (args.client) {\n // eslint-disable-next-line no-console\n console.log('Client ID: %s (%s)', args.client.id, args.client.frameType)\n }\n\n console.groupEnd()\n}\n","import { DeferredPromise } from '@open-draft/deferred-promise'\nimport type { StartOptions, SetupWorkerInternalContext } from '../../glossary'\nimport { printStartMessage } from './printStartMessage'\n\n/**\n * Signals the worker to enable the interception of requests.\n */\nexport function enableMocking(\n context: SetupWorkerInternalContext,\n options: StartOptions,\n): Promise<boolean> {\n const mockingEnabledPromise = new DeferredPromise<boolean>()\n\n context.workerChannel.postMessage('MOCK_ACTIVATE')\n context.workerChannel.once('MOCKING_ENABLED', async (event) => {\n context.isMockingEnabled = true\n const worker = await context.workerPromise\n\n printStartMessage({\n quiet: options.quiet,\n workerScope: context.registration?.scope,\n workerUrl: worker.scriptURL,\n client: event.data.client,\n })\n\n mockingEnabledPromise.resolve(true)\n })\n\n return mockingEnabledPromise\n}\n","import type { ServiceWorkerIncomingRequest } from '../setupWorker/glossary'\n\ntype Input = Pick<ServiceWorkerIncomingRequest, 'method' | 'body'>\n\n/**\n * Ensures that an empty GET request body is always represented as `undefined`.\n */\nexport function pruneGetRequestBody(\n request: Input,\n): ServiceWorkerIncomingRequest['body'] {\n // Force HEAD/GET request body to always be empty.\n // The worker reads any request's body as ArrayBuffer,\n // and you cannot re-construct a GET/HEAD Request\n // with an ArrayBuffer, even if empty. Also note that\n // \"request.body\" is always undefined in the worker.\n if (['HEAD', 'GET'].includes(request.method)) {\n return undefined\n }\n\n return request.body\n}\n","import { pruneGetRequestBody } from './pruneGetRequestBody'\nimport type { ServiceWorkerIncomingRequest } from '../setupWorker/glossary'\n\n/**\n * Converts a given request received from the Service Worker\n * into a Fetch `Request` instance.\n */\nexport function deserializeRequest(\n serializedRequest: ServiceWorkerIncomingRequest,\n): Request {\n return new Request(serializedRequest.url, {\n ...serializedRequest,\n body: pruneGetRequestBody(serializedRequest),\n })\n}\n","import { Emitter } from 'rettime'\nimport { StartOptions, SetupWorkerInternalContext } from '../glossary'\nimport { deserializeRequest } from '../../utils/deserializeRequest'\nimport { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport { RequiredDeep } from '~/core/typeUtils'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport { toResponseInit } from '~/core/utils/toResponseInit'\nimport { isHandlerKind } from '~/core/utils/internal/isHandlerKind'\n\nexport const createRequestListener = (\n context: SetupWorkerInternalContext,\n options: RequiredDeep<StartOptions>,\n): Emitter.ListenerType<typeof context.workerChannel, 'REQUEST'> => {\n return async (event) => {\n // Treat any incoming requests from the worker as passthrough\n // if `worker.stop()` has been called for this client.\n if (\n !context.isMockingEnabled &&\n context.workerStoppedAt &&\n event.data.interceptedAt > context.workerStoppedAt\n ) {\n event.postMessage('PASSTHROUGH')\n return\n }\n\n const requestId = event.data.id\n const request = deserializeRequest(event.data)\n const requestCloneForLogs = request.clone()\n\n // Make this the first request clone before the\n // request resolution pipeline even starts.\n // Store the clone in cache so the first matching\n // request handler would skip the cloning phase.\n const requestClone = request.clone()\n RequestHandler.cache.set(request, requestClone)\n\n try {\n await handleRequest(\n request,\n requestId,\n context.getRequestHandlers().filter(isHandlerKind('RequestHandler')),\n options,\n context.emitter,\n {\n onPassthroughResponse() {\n event.postMessage('PASSTHROUGH')\n },\n async onMockedResponse(response, { handler, parsedResult }) {\n // Clone the mocked response so its body could be read\n // to buffer to be sent to the worker and also in the\n // \".log()\" method of the request handler.\n const responseClone = response.clone()\n const responseCloneForLogs = response.clone()\n const responseInit = toResponseInit(response)\n\n /**\n * @note Safari doesn't support transferring a \"ReadableStream\".\n * Check that the browser supports that before sending it to the worker.\n */\n if (context.supports.readableStreamTransfer) {\n const responseStreamOrNull = response.body\n\n event.postMessage(\n 'MOCK_RESPONSE',\n {\n ...responseInit,\n body: responseStreamOrNull,\n },\n responseStreamOrNull ? [responseStreamOrNull] : undefined,\n )\n } else {\n /**\n * @note If we are here, this means the current environment doesn't\n * support \"ReadableStream\" as transferable. In that case,\n * attempt to read the non-empty response body as ArrayBuffer, if it's not empty.\n * @see https://github.com/mswjs/msw/issues/1827\n */\n const responseBufferOrNull =\n response.body === null\n ? null\n : await responseClone.arrayBuffer()\n\n event.postMessage('MOCK_RESPONSE', {\n ...responseInit,\n body: responseBufferOrNull,\n })\n }\n\n if (!options.quiet) {\n context.emitter.once('response:mocked', () => {\n handler.log({\n request: requestCloneForLogs,\n response: responseCloneForLogs,\n parsedResult,\n })\n })\n }\n },\n },\n )\n } catch (error) {\n if (error instanceof Error) {\n devUtils.error(\n `Uncaught exception in the request handler for \"%s %s\":\n\n%s\n\nThis 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 request.method,\n request.url,\n error.stack ?? error,\n )\n\n // Treat all other exceptions in a request handler as unintended,\n // alerting that there is a problem that needs fixing.\n event.postMessage('MOCK_RESPONSE', {\n status: 500,\n statusText: 'Request Handler Error',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n name: error.name,\n message: error.message,\n stack: error.stack,\n }),\n })\n }\n }\n }\n}\n","import { devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupWorkerInternalContext } from '../setupWorker/glossary'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\n\n/**\n * Check whether the registered Service Worker has been\n * generated by the installed version of the library.\n * Prints a warning message if the worker scripts mismatch.\n */\nexport function checkWorkerIntegrity(\n context: SetupWorkerInternalContext,\n): Promise<void> {\n const integrityCheckPromise = new DeferredPromise<void>()\n\n // Request the integrity checksum from the registered worker.\n context.workerChannel.postMessage('INTEGRITY_CHECK_REQUEST')\n context.workerChannel.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\n}\n","const encoder = new TextEncoder()\n\nexport function encodeBuffer(text: string): Uint8Array {\n return encoder.encode(text)\n}\n\nexport function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string {\n const decoder = new TextDecoder(encoding)\n return decoder.decode(buffer)\n}\n\n/**\n * Create an `ArrayBuffer` from the given `Uint8Array`.\n * Takes the byte offset into account to produce the right buffer\n * in the case when the buffer is bigger than the data view.\n */\nexport function toArrayBuffer(array: Uint8Array): ArrayBuffer {\n return array.buffer.slice(\n array.byteOffset,\n array.byteOffset + array.byteLength\n )\n}\n","import type { RequestController } from './RequestController'\n\nexport const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')\n\n/**\n * @note Export `RequestController` as a type only.\n * It's never meant to be created in the userland.\n */\nexport type { RequestController }\n\nexport type RequestCredentials = 'omit' | 'include' | 'same-origin'\n\nexport type HttpRequestEventMap = {\n request: [\n args: {\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n response: [\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ]\n unhandledException: [\n args: {\n error: unknown\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n","/**\n * Returns the value behind the symbol with the given name.\n */\nexport function getValueBySymbol<T>(\n symbolName: string,\n source: object\n): T | undefined {\n const ownSymbols = Object.getOwnPropertySymbols(source)\n\n const symbol = ownSymbols.find((symbol) => {\n return symbol.description === symbolName\n })\n\n if (symbol) {\n return Reflect.get(source, symbol)\n }\n\n return\n}\n","import { canParseUrl } from './canParseUrl'\nimport { getValueBySymbol } from './getValueBySymbol'\n\nexport interface FetchResponseInit extends ResponseInit {\n url?: string\n}\n\ninterface UndiciFetchInternalState {\n aborted: boolean\n rangeRequested: boolean\n timingAllowPassed: boolean\n requestIncludesCredentials: boolean\n type: ResponseType\n status: number\n statusText: string\n timingInfo: unknown\n cacheState: unknown\n headersList: Record<symbol, Map<string, unknown>>\n urlList: Array<URL>\n body?: {\n stream: ReadableStream\n source: unknown\n length: number\n }\n}\n\nexport class FetchResponse extends Response {\n /**\n * Response status codes for responses that cannot have body.\n * @see https://fetch.spec.whatwg.org/#statuses\n */\n static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n static isConfigurableStatusCode(status: number): boolean {\n return status >= 200 && status <= 599\n }\n\n static isRedirectResponse(status: number): boolean {\n return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n }\n\n /**\n * Returns a boolean indicating whether the given response status\n * code represents a response that can have a body.\n */\n static isResponseWithBody(status: number): boolean {\n return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n }\n\n static setUrl(url: string | undefined, response: Response): void {\n if (!url || url === 'about:' || !canParseUrl(url)) {\n return\n }\n\n const state = getValueBySymbol<UndiciFetchInternalState>('state', response)\n\n if (state) {\n // In Undici, push the URL to the internal list of URLs.\n // This will respect the `response.url` getter logic correctly.\n state.urlList.push(new URL(url))\n } else {\n // In other libraries, redefine the `url` property directly.\n Object.defineProperty(response, 'url', {\n value: url,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n\n /**\n * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n */\n static parseRawHeaders(rawHeaders: Array<string>): Headers {\n const headers = new Headers()\n for (let line = 0; line < rawHeaders.length; line += 2) {\n headers.append(rawHeaders[line], rawHeaders[line + 1])\n }\n return headers\n }\n\n constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n const status = init.status ?? 200\n const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n ? status\n : 200\n const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n super(finalBody, {\n status: safeStatus,\n statusText: init.statusText,\n headers: init.headers,\n })\n\n if (status !== safeStatus) {\n /**\n * @note Undici keeps an internal \"Symbol(state)\" that holds\n * the actual value of response status. Update that in Node.js.\n */\n const state = getValueBySymbol<UndiciFetchInternalState>('state', this)\n\n if (state) {\n state.status = status\n } else {\n Object.defineProperty(this, 'status', {\n value: status,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n\n FetchResponse.setUrl(init.url, this)\n }\n}\n","const kRawRequest = Symbol('kRawRequest')\n\n/**\n * Returns a raw request instance associated with this request.\n *\n * @example\n * interceptor.on('request', ({ request }) => {\n * const rawRequest = getRawRequest(request)\n *\n * if (rawRequest instanceof http.ClientRequest) {\n * console.log(rawRequest.rawHeaders)\n * }\n * })\n */\nexport function getRawRequest(request: Request): unknown | undefined {\n return Reflect.get(request, kRawRequest)\n}\n\nexport function setRawRequest(request: Request, rawRequest: unknown): void {\n Reflect.set(request, kRawRequest, rawRequest)\n}\n","var __defProp = Object.defineProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\n\n// src/index.ts\nimport { isNodeProcess } from \"is-node-process\";\nimport { format } from \"outvariant\";\n\n// src/colors.ts\nvar colors_exports = {};\n__export(colors_exports, {\n blue: () => blue,\n gray: () => gray,\n green: () => green,\n red: () => red,\n yellow: () => yellow\n});\nfunction yellow(text) {\n return `\\x1B[33m${text}\\x1B[0m`;\n}\nfunction blue(text) {\n return `\\x1B[34m${text}\\x1B[0m`;\n}\nfunction gray(text) {\n return `\\x1B[90m${text}\\x1B[0m`;\n}\nfunction red(text) {\n return `\\x1B[31m${text}\\x1B[0m`;\n}\nfunction green(text) {\n return `\\x1B[32m${text}\\x1B[0m`;\n}\n\n// src/index.ts\nvar IS_NODE = isNodeProcess();\nvar Logger = class {\n constructor(name) {\n this.name = name;\n this.prefix = `[${this.name}]`;\n const LOGGER_NAME = getVariable(\"DEBUG\");\n const LOGGER_LEVEL = getVariable(\"LOG_LEVEL\");\n const isLoggingEnabled = LOGGER_NAME === \"1\" || LOGGER_NAME === \"true\" || typeof LOGGER_NAME !== \"undefined\" && this.name.startsWith(LOGGER_NAME);\n if (isLoggingEnabled) {\n this.debug = isDefinedAndNotEquals(LOGGER_LEVEL, \"debug\") ? noop : this.debug;\n this.info = isDefinedAndNotEquals(LOGGER_LEVEL, \"info\") ? noop : this.info;\n this.success = isDefinedAndNotEquals(LOGGER_LEVEL, \"success\") ? noop : this.success;\n this.warning = isDefinedAndNotEquals(LOGGER_LEVEL, \"warning\") ? noop : this.warning;\n this.error = isDefinedAndNotEquals(LOGGER_LEVEL, \"error\") ? noop : this.error;\n } else {\n this.info = noop;\n this.success = noop;\n this.warning = noop;\n this.error = noop;\n this.only = noop;\n }\n }\n prefix;\n extend(domain) {\n return new Logger(`${this.name}:${domain}`);\n }\n /**\n * Print a debug message.\n * @example\n * logger.debug('no duplicates found, creating a document...')\n */\n debug(message, ...positionals) {\n this.logEntry({\n level: \"debug\",\n message: gray(message),\n positionals,\n prefix: this.prefix,\n colors: {\n prefix: \"gray\"\n }\n });\n }\n /**\n * Print an info message.\n * @example\n * logger.info('start parsing...')\n */\n info(message, ...positionals) {\n this.logEntry({\n level: \"info\",\n message,\n positionals,\n prefix: this.prefix,\n colors: {\n prefix: \"blue\"\n }\n });\n const performance2 = new PerformanceEntry();\n return (message2, ...positionals2) => {\n performance2.measure();\n this.logEntry({\n level: \"info\",\n message: `${message2} ${gray(`${performance2.deltaTime}ms`)}`,\n positionals: positionals2,\n prefix: this.prefix,\n colors: {\n prefix: \"blue\"\n }\n });\n };\n }\n /**\n * Print a success message.\n * @example\n * logger.success('successfully created document')\n */\n success(message, ...positionals) {\n this.logEntry({\n level: \"info\",\n message,\n positionals,\n prefix: `\\u2714 ${this.prefix}`,\n colors: {\n timestamp: \"green\",\n prefix: \"green\"\n }\n });\n }\n /**\n * Print a warning.\n * @example\n * logger.warning('found legacy document format')\n */\n warning(message, ...positionals) {\n this.logEntry({\n level: \"warning\",\n message,\n positionals,\n prefix: `\\u26A0 ${this.prefix}`,\n colors: {\n timestamp: \"yellow\",\n prefix: \"yellow\"\n }\n });\n }\n /**\n * Print an error message.\n * @example\n * logger.error('something went wrong')\n */\n error(message, ...positionals) {\n this.logEntry({\n level: \"error\",\n message,\n positionals,\n prefix: `\\u2716 ${this.prefix}`,\n colors: {\n timestamp: \"red\",\n prefix: \"red\"\n }\n });\n }\n /**\n * Execute the given callback only when the logging is enabled.\n * This is skipped in its entirety and has no runtime cost otherwise.\n * This executes regardless of the log level.\n * @example\n * logger.only(() => {\n * logger.info('additional info')\n * })\n */\n only(callback) {\n callback();\n }\n createEntry(level, message) {\n return {\n timestamp: /* @__PURE__ */ new Date(),\n level,\n message\n };\n }\n logEntry(args) {\n const {\n level,\n message,\n prefix,\n colors: customColors,\n positionals = []\n } = args;\n const entry = this.createEntry(level, message);\n const timestampColor = customColors?.timestamp || \"gray\";\n const prefixColor = customColors?.prefix || \"gray\";\n const colorize = {\n timestamp: colors_exports[timestampColor],\n prefix: colors_exports[prefixColor]\n };\n const write = this.getWriter(level);\n write(\n [colorize.timestamp(this.formatTimestamp(entry.timestamp))].concat(prefix != null ? colorize.prefix(prefix) : []).concat(serializeInput(message)).join(\" \"),\n ...positionals.map(serializeInput)\n );\n }\n formatTimestamp(timestamp) {\n return `${timestamp.toLocaleTimeString(\n \"en-GB\"\n )}:${timestamp.getMilliseconds()}`;\n }\n getWriter(level) {\n switch (level) {\n case \"debug\":\n case \"success\":\n case \"info\": {\n return log;\n }\n case \"warning\": {\n return warn;\n }\n case \"error\": {\n return error;\n }\n }\n }\n};\nvar PerformanceEntry = class {\n startTime;\n endTime;\n deltaTime;\n constructor() {\n this.startTime = performance.now();\n }\n measure() {\n this.endTime = performance.now();\n const deltaTime = this.endTime - this.startTime;\n this.deltaTime = deltaTime.toFixed(2);\n }\n};\nvar noop = () => void 0;\nfunction log(message, ...positionals) {\n if (IS_NODE) {\n process.stdout.write(format(message, ...positionals) + \"\\n\");\n return;\n }\n console.log(message, ...positionals);\n}\nfunction warn(message, ...positionals) {\n if (IS_NODE) {\n process.stderr.write(format(message, ...positionals) + \"\\n\");\n return;\n }\n console.warn(message, ...positionals);\n}\nfunction error(message, ...positionals) {\n if (IS_NODE) {\n process.stderr.write(format(message, ...positionals) + \"\\n\");\n return;\n }\n console.error(message, ...positionals);\n}\nfunction getVariable(variableName) {\n if (IS_NODE) {\n return process.env[variableName];\n }\n return globalThis[variableName]?.toString();\n}\nfunction isDefinedAndNotEquals(value, expected) {\n return value !== void 0 && value !== expected;\n}\nfunction serializeInput(message) {\n if (typeof message === \"undefined\") {\n return \"undefined\";\n }\n if (message === null) {\n retur