@depup/msw 3.0.0-depup.0 → 3.0.1-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 CHANGED
@@ -13,8 +13,8 @@ npm install @depup/msw
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [msw](https://www.npmjs.com/package/msw) @ 3.0.0 |
17
- | Processed | 2026-09-28 |
16
+ | Original | [msw](https://www.npmjs.com/package/msw) @ 3.0.1 |
17
+ | Processed | 2026-09-30 |
18
18
  | Smoke test | passed |
19
19
  | Deps updated | 2 |
20
20
 
package/changes.json CHANGED
@@ -9,6 +9,6 @@
9
9
  "to": "^5.10.0"
10
10
  }
11
11
  },
12
- "timestamp": "2026-09-28T16:11:01.003Z",
12
+ "timestamp": "2026-09-30T16:12:49.570Z",
13
13
  "totalUpdated": 2
14
14
  }
@@ -1,4 +1,4 @@
1
- import { a as matchRequestUrl, g as Handler, h as getCallFrame, m as devUtils, o as isAbsoluteUrl, r as toPublicUrl, s as getTimestamp } from "./cookie-store.js";
1
+ import { _ as Handler, a as matchRequestUrl, g as getCallFrame, h as devUtils, o as isAbsoluteUrl, r as toPublicUrl, s as getTimestamp } from "./cookie-store.js";
2
2
  import { t as isObject } from "./is-object.js";
3
3
  import { t as colors } from "./colors.js";
4
4
  import { invariant } from "outvariant";
@@ -205,6 +205,14 @@ function copyResponseOwnProperties(source, target) {
205
205
  }
206
206
  }
207
207
  //#endregion
208
+ //#region src/core/utils/internal/is-string-equal.ts
209
+ /**
210
+ * Performs a case-insensitive comparison of two given strings.
211
+ */
212
+ function isStringEqual(actual, expected) {
213
+ return actual.toLowerCase() === expected.toLowerCase();
214
+ }
215
+ //#endregion
208
216
  //#region src/core/utils/logging/get-timestamp.ts
209
217
  /**
210
218
  * Returns a timestamp string in a "HH:MM:SS" format.
@@ -343,6 +351,6 @@ var CookieStore = class {
343
351
  };
344
352
  const cookieStore = isNodeProcess() ? null : new CookieStore();
345
353
  //#endregion
346
- export { matchRequestUrl as a, copyResponseOwnProperties as c, normalizeResponseInit as d, httpStatusMessages as f, Handler as g, getCallFrame as h, isPath as i, decorateResponse as l, devUtils as m, jsonParse as n, isAbsoluteUrl as o, InternalError as p, toPublicUrl as r, getTimestamp as s, cookieStore as t, getRawSetCookie as u };
354
+ export { Handler as _, matchRequestUrl as a, isStringEqual as c, getRawSetCookie as d, normalizeResponseInit as f, getCallFrame as g, devUtils as h, isPath as i, copyResponseOwnProperties as l, InternalError as m, jsonParse as n, isAbsoluteUrl as o, httpStatusMessages as p, toPublicUrl as r, getTimestamp as s, cookieStore as t, decorateResponse as u };
347
355
 
348
356
  //# sourceMappingURL=cookie-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cookie-store.js","names":[],"sources":["../../src/core/handlers/handler.ts","../../src/core/utils/internal/get-call-frame.ts","../../src/core/utils/internal/dev-utils.ts","../../src/core/utils/http-status-messages.ts","../../src/core/utils/response-decorators.ts","../../src/core/utils/logging/get-timestamp.ts","../../src/core/utils/url/is-absolute-url.ts","../../src/core/utils/url/get-absolute-url.ts","../../src/core/utils/matching/normalize-path.ts","../../src/core/utils/matching/match-request-url.ts","../../src/core/utils/request/to-public-url.ts","../../src/core/utils/internal/json-parse.ts","../../src/core/utils/cookie-store.ts"],"sourcesContent":["import type { MaybePromise } from '../type-utils'\n\nexport type HandlerKind = 'request' | 'websocket'\n\n/**\n * The base class for all the handlers.\n */\nexport abstract class Handler {\n /**\n * The kind of the network frame this handler handles.\n */\n abstract readonly kind: HandlerKind\n\n /**\n * Reset the runtime state this handler accumulated while handling\n * the network (e.g. generator resolver progress).\n *\n * @note This method is invoked automatically when the handlers are\n * reset (e.g. `server.resetHandlers()`).\n */\n public reset(): void {}\n\n /**\n * Restore this handler so it can handle the network again after\n * being exhausted (e.g. via `{ once: true }`).\n *\n * @note This method is invoked automatically when the handlers are\n * restored (e.g. `server.restoreHandlers()`).\n */\n public restore(): void {}\n\n /**\n * Release the resources held by this handler.\n *\n * @note This method is invoked automatically when the network is\n * disabled (e.g. `server.close()`). Override it in the handlers that\n * hold onto anything beyond a single frame, like timers, connections,\n * or event listeners. Returning a promise makes the network await\n * this handler's disposal before it tears itself down.\n */\n public dispose(): MaybePromise<void> {}\n}\n","// Ignore the source files traces for local testing.\nconst SOURCE_FRAME = /[/\\\\]msw[/\\\\]src[/\\\\](.+)/\n\nconst BUILD_FRAME =\n /(node_modules)?[/\\\\]lib[/\\\\](core|browser|node|iife)[/\\\\]|^[^/\\\\]*$/\n\n/**\n * Return the stack trace frame of a function's invocation.\n */\nexport function getCallFrame(error: Error) {\n // In <IE11, new Error may return an undefined stack\n const stack = error.stack\n\n if (!stack) {\n return\n }\n\n const frames: string[] = stack.split('\\n').slice(1)\n\n // Get the first frame that doesn't reference the library's internal trace.\n // Assume that frame is the invocation frame.\n const declarationFrame = frames.find((frame) => {\n return !(SOURCE_FRAME.test(frame) || BUILD_FRAME.test(frame))\n })\n\n if (!declarationFrame) {\n return\n }\n\n // Extract file reference from the stack frame.\n const declarationPath = declarationFrame\n .replace(/\\s*at [^()]*\\(([^)]+)\\)/, '$1')\n .replace(/^@/, '')\n return declarationPath\n}\n","import { format } from 'outvariant'\n\nconst LIBRARY_PREFIX = '[MSW]'\n\n/**\n * Formats a given message by appending the library's prefix string.\n */\nfunction formatMessage(message: string, ...positionals: any[]): string {\n const interpolatedMessage = format(message, ...positionals)\n return `${LIBRARY_PREFIX} ${interpolatedMessage}`\n}\n\n/**\n * Prints a library-specific warning.\n */\nfunction warn(message: string, ...positionals: any[]): void {\n console.warn(formatMessage(message, ...positionals))\n}\n\n/**\n * Prints a library-specific error.\n */\nfunction error(message: string, ...positionals: any[]): void {\n console.error(formatMessage(message, ...positionals))\n}\n\nexport const devUtils = {\n formatMessage,\n warn,\n error,\n}\n\n/**\n * Internal error instance.\n * Used to differentiate the library errors that must be forwarded\n * to the user from the unhandled exceptions. Use this if you don't\n * wish for the error to be coerced to a 500 fallback response.\n */\nexport class InternalError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'InternalError'\n }\n}\n","/**\n * Reason phrases of the known HTTP status codes.\n * @see https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml\n */\nexport const httpStatusMessages: Record<number, string> = {\n 100: 'Continue',\n 101: 'Switching Protocols',\n 102: 'Processing',\n 103: 'Early Hints',\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 203: 'Non-Authoritative Information',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 207: 'Multi-Status',\n 208: 'Already Reported',\n 226: 'IM Used',\n 300: 'Multiple Choices',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 305: 'Use Proxy',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 407: 'Proxy Authentication Required',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 417: 'Expectation Failed',\n 418: \"I'm a Teapot\",\n 421: 'Misdirected Request',\n 422: 'Unprocessable Entity',\n 423: 'Locked',\n 424: 'Failed Dependency',\n 425: 'Too Early',\n 426: 'Upgrade Required',\n 428: 'Precondition Required',\n 429: 'Too Many Requests',\n 431: 'Request Header Fields Too Large',\n 451: 'Unavailable For Legal Reasons',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n 506: 'Variant Also Negotiates',\n 507: 'Insufficient Storage',\n 508: 'Loop Detected',\n 509: 'Bandwidth Limit Exceeded',\n 510: 'Not Extended',\n 511: 'Network Authentication Required',\n}\n","import type { HttpResponse, HttpResponseInit } from '#http/http-response'\nimport { httpStatusMessages } from './http-status-messages'\n\nconst kSetCookie = Symbol('kSetCookie')\n\nexport interface HttpResponseDecoratedInit extends HttpResponseInit {\n status: number\n statusText: string\n headers: Headers\n}\n\nexport function normalizeResponseInit(\n init: HttpResponseInit = {},\n): HttpResponseDecoratedInit {\n const status = init?.status || 200\n const statusText = init?.statusText || httpStatusMessages[status] || ''\n const headers = new Headers(init?.headers)\n\n return {\n ...init,\n headers,\n status,\n statusText,\n }\n}\n\nexport function decorateResponse(\n response: HttpResponse<any>,\n init: HttpResponseDecoratedInit,\n): Response {\n // Allow mocking the response type.\n if (init.type) {\n Object.defineProperty(response, 'type', {\n value: init.type,\n enumerable: true,\n writable: false,\n })\n }\n\n const responseCookies = init.headers.getSetCookie()\n\n if (responseCookies) {\n // Record the raw \"Set-Cookie\" response header provided\n // in the HeadersInit. This is later used to store these cookies\n // in cookie jar and return the right cookies in the \"cookies\"\n // response resolver argument.\n Object.defineProperty(response, kSetCookie, {\n value: responseCookies,\n enumerable: false,\n writable: false,\n })\n }\n\n return response\n}\n\nexport function getRawSetCookie(response: Response): Array<string> {\n return Reflect.get(response, kSetCookie) || []\n}\n\n/**\n * Copy the given response own properties, like internal symbols,\n * onto another response. Used for faithful internal copying of responses.\n */\nexport function copyResponseOwnProperties(\n source: Response,\n target: Response,\n): void {\n for (const propertyName of Reflect.ownKeys(source)) {\n const descriptor = Object.getOwnPropertyDescriptor(source, propertyName)\n const existingDescriptor = Object.getOwnPropertyDescriptor(\n target,\n propertyName,\n )\n\n if (descriptor && existingDescriptor == null) {\n Object.defineProperty(target, propertyName, descriptor)\n }\n }\n}\n","interface GetTimestampOptions {\n milliseconds?: boolean\n}\n\n/**\n * Returns a timestamp string in a \"HH:MM:SS\" format.\n */\nexport function getTimestamp(options?: GetTimestampOptions): string {\n const now = new Date()\n const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`\n\n if (options?.milliseconds) {\n return `${timestamp}.${now.getMilliseconds().toString().padStart(3, '0')}`\n }\n\n return timestamp\n}\n","/**\n * Determines if the given URL string is an absolute URL.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url)\n}\n","import { isAbsoluteUrl } from './is-absolute-url'\n\n/**\n * Returns an absolute URL based on the given path.\n */\nexport function getAbsoluteUrl(path: string, baseUrl?: string): string {\n // already absolute URL\n if (isAbsoluteUrl(path)) {\n return path\n }\n\n // Ignore path with pattern start with *\n if (path.startsWith('*')) {\n return path\n }\n\n // Resolve a relative request URL against a given custom \"baseUrl\"\n // or the document baseURI (in the case of browser/browser-like environments).\n const origin = baseUrl || (typeof location !== 'undefined' && location.href)\n\n return origin\n ? // Encode and decode the path to preserve escaped characters.\n decodeURI(new URL(encodeURI(path), origin).href)\n : path\n}\n","import type { Path } from './match-request-url'\nimport { getCleanUrlString } from '#utils/get-clean-url-string'\nimport { getAbsoluteUrl } from '../url/get-absolute-url'\n\n/**\n * Normalizes a given request handler path:\n * - Preserves RegExp.\n * - Removes query parameters and hashes.\n * - Rebases relative URLs against the \"baseUrl\" or the current location.\n * - Preserves relative URLs in Node.js, unless specified otherwise.\n * - Preserves optional path parameters.\n */\nexport function normalizePath<ThisPath extends Path>(\n path: ThisPath,\n baseUrl?: string,\n): ThisPath {\n // RegExp paths do not need normalization.\n if (path instanceof RegExp) {\n return path\n }\n\n const maybeAbsoluteUrl = getAbsoluteUrl(path, baseUrl)\n\n return getCleanUrlString(maybeAbsoluteUrl) as ThisPath\n}\n","import { matchPattern } from '@msw/url'\nimport { getCleanUrl } from '@mswjs/interceptors'\nimport { normalizePath } from './normalize-path'\n\nexport type Path = string | RegExp\nexport type PathParams<KeyType extends keyof any = string> = {\n [ParamName in KeyType]?: string | ReadonlyArray<string>\n}\n\nexport interface Match {\n matches: boolean\n params?: PathParams\n}\n\nexport function isPath(value: unknown): value is Path {\n return typeof value === 'string' || value instanceof RegExp\n}\n\n/**\n * Match the given URL against a path pattern.\n */\nexport function matchRequestUrl(\n url: URL,\n pattern: Path,\n baseUrl?: string,\n): Match {\n const cleanUrl = getCleanUrl(url)\n\n if (pattern instanceof RegExp) {\n const match = pattern.flags.includes('g')\n ? [...cleanUrl.matchAll(pattern)].flat()\n : cleanUrl.match(pattern)\n\n return {\n matches: match != null && match.length > 0,\n params: Object.fromEntries(\n (match ?? []).slice(1).map((value, index) => [index, value]),\n ),\n }\n }\n\n // Resolve potentially realive patterns against the baseUrl.\n const normalizedPath = normalizePath(pattern, baseUrl)\n return matchPattern(normalizedPath, cleanUrl)\n}\n","/**\n * Returns a relative URL if the given request URL is relative\n * to the current origin. Otherwise returns an absolute URL.\n */\nexport function toPublicUrl(url: string | URL): string {\n const urlInstance = url instanceof URL ? url : new URL(url)\n\n if (\n typeof location !== 'undefined' &&\n urlInstance.origin === location.origin\n ) {\n return urlInstance.pathname\n }\n\n return urlInstance.origin + urlInstance.pathname\n}\n","/**\n * Parses a given value into a JSON.\n * Does not throw an exception on an invalid JSON string.\n */\nexport function jsonParse<ValueType extends Record<string, any>>(\n value: any,\n): ValueType | undefined {\n try {\n return JSON.parse(value)\n } catch {\n return undefined\n }\n}\n","import { isNodeProcess } from 'is-node-process'\nimport { invariant } from 'outvariant'\nimport {\n Cookie,\n CookieJar,\n MemoryCookieStore,\n type SerializedCookie,\n type MemoryCookieStoreIndex,\n} from 'tough-cookie'\nimport { jsonParse } from './internal/json-parse'\n\nclass CookieStore {\n #storageKey = '__msw-cookie-store__'\n #jar: CookieJar\n #memoryStore: MemoryCookieStore\n\n constructor() {\n invariant(\n typeof localStorage !== 'undefined',\n 'Failed to create a CookieStore: `localStorage` is not available in this environment. This is likely an issue with your environment, which has been detected as browser (or browser-like) environment and must implement global browser APIs correctly.',\n )\n\n this.#memoryStore = new MemoryCookieStore()\n this.#memoryStore.idx = this.getCookieStoreIndex()\n this.#jar = new CookieJar(this.#memoryStore)\n }\n\n public getCookies(url: string): Array<Cookie> {\n return this.#jar.getCookiesSync(url)\n }\n\n public async setCookie(cookieName: string, url: string): Promise<void> {\n await this.#jar.setCookie(cookieName, url)\n this.persist()\n }\n\n private getCookieStoreIndex(): MemoryCookieStoreIndex {\n if (\n typeof localStorage === 'undefined' ||\n typeof localStorage.getItem !== 'function'\n ) {\n return {}\n }\n\n const cookiesString = localStorage.getItem(this.#storageKey)\n if (cookiesString == null) {\n return {}\n }\n\n const rawCookies = jsonParse<Array<Record<string, unknown>>>(cookiesString)\n if (rawCookies == null) {\n return {}\n }\n\n const cookies: MemoryCookieStoreIndex = {}\n\n for (const rawCookie of rawCookies) {\n const cookie = Cookie.fromJSON(rawCookie)\n\n if (cookie != null && cookie.domain != null && cookie.path != null) {\n cookies[cookie.domain] ||= {}\n cookies[cookie.domain][cookie.path] ||= {}\n cookies[cookie.domain][cookie.path][cookie.key] = cookie\n }\n }\n\n return cookies\n }\n\n private persist(): void {\n if (\n typeof localStorage === 'undefined' ||\n typeof localStorage.setItem !== 'function'\n ) {\n return\n }\n\n const data: Array<SerializedCookie> = []\n const { idx } = this.#memoryStore\n\n for (const domain in idx) {\n for (const path in idx[domain]) {\n for (const key in idx[domain][path]) {\n data.push(idx[domain][path][key].toJSON())\n }\n }\n }\n\n try {\n localStorage.setItem(this.#storageKey, JSON.stringify(data))\n } catch {\n // Persisting cookies is best-effort. If the storage quota is exceeded,\n // keep the cookies in memory so the request handling continues.\n return\n }\n }\n}\n\n// Node.js has no implicit cookie jar. Leave cookie management to the client.\nexport const cookieStore = isNodeProcess() ? null : new CookieStore()\n"],"mappings":"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"}
1
+ {"version":3,"file":"cookie-store.js","names":[],"sources":["../../src/core/handlers/handler.ts","../../src/core/utils/internal/get-call-frame.ts","../../src/core/utils/internal/dev-utils.ts","../../src/core/utils/http-status-messages.ts","../../src/core/utils/response-decorators.ts","../../src/core/utils/internal/is-string-equal.ts","../../src/core/utils/logging/get-timestamp.ts","../../src/core/utils/url/is-absolute-url.ts","../../src/core/utils/url/get-absolute-url.ts","../../src/core/utils/matching/normalize-path.ts","../../src/core/utils/matching/match-request-url.ts","../../src/core/utils/request/to-public-url.ts","../../src/core/utils/internal/json-parse.ts","../../src/core/utils/cookie-store.ts"],"sourcesContent":["import type { MaybePromise } from '../type-utils'\n\nexport type HandlerKind = 'request' | 'websocket'\n\n/**\n * The base class for all the handlers.\n */\nexport abstract class Handler {\n /**\n * The kind of the network frame this handler handles.\n */\n abstract readonly kind: HandlerKind\n\n /**\n * Reset the runtime state this handler accumulated while handling\n * the network (e.g. generator resolver progress).\n *\n * @note This method is invoked automatically when the handlers are\n * reset (e.g. `server.resetHandlers()`).\n */\n public reset(): void {}\n\n /**\n * Restore this handler so it can handle the network again after\n * being exhausted (e.g. via `{ once: true }`).\n *\n * @note This method is invoked automatically when the handlers are\n * restored (e.g. `server.restoreHandlers()`).\n */\n public restore(): void {}\n\n /**\n * Release the resources held by this handler.\n *\n * @note This method is invoked automatically when the network is\n * disabled (e.g. `server.close()`). Override it in the handlers that\n * hold onto anything beyond a single frame, like timers, connections,\n * or event listeners. Returning a promise makes the network await\n * this handler's disposal before it tears itself down.\n */\n public dispose(): MaybePromise<void> {}\n}\n","// Ignore the source files traces for local testing.\nconst SOURCE_FRAME = /[/\\\\]msw[/\\\\]src[/\\\\](.+)/\n\nconst BUILD_FRAME =\n /(node_modules)?[/\\\\]lib[/\\\\](core|browser|node|iife)[/\\\\]|^[^/\\\\]*$/\n\n/**\n * Return the stack trace frame of a function's invocation.\n */\nexport function getCallFrame(error: Error) {\n // In <IE11, new Error may return an undefined stack\n const stack = error.stack\n\n if (!stack) {\n return\n }\n\n const frames: string[] = stack.split('\\n').slice(1)\n\n // Get the first frame that doesn't reference the library's internal trace.\n // Assume that frame is the invocation frame.\n const declarationFrame = frames.find((frame) => {\n return !(SOURCE_FRAME.test(frame) || BUILD_FRAME.test(frame))\n })\n\n if (!declarationFrame) {\n return\n }\n\n // Extract file reference from the stack frame.\n const declarationPath = declarationFrame\n .replace(/\\s*at [^()]*\\(([^)]+)\\)/, '$1')\n .replace(/^@/, '')\n return declarationPath\n}\n","import { format } from 'outvariant'\n\nconst LIBRARY_PREFIX = '[MSW]'\n\n/**\n * Formats a given message by appending the library's prefix string.\n */\nfunction formatMessage(message: string, ...positionals: any[]): string {\n const interpolatedMessage = format(message, ...positionals)\n return `${LIBRARY_PREFIX} ${interpolatedMessage}`\n}\n\n/**\n * Prints a library-specific warning.\n */\nfunction warn(message: string, ...positionals: any[]): void {\n console.warn(formatMessage(message, ...positionals))\n}\n\n/**\n * Prints a library-specific error.\n */\nfunction error(message: string, ...positionals: any[]): void {\n console.error(formatMessage(message, ...positionals))\n}\n\nexport const devUtils = {\n formatMessage,\n warn,\n error,\n}\n\n/**\n * Internal error instance.\n * Used to differentiate the library errors that must be forwarded\n * to the user from the unhandled exceptions. Use this if you don't\n * wish for the error to be coerced to a 500 fallback response.\n */\nexport class InternalError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'InternalError'\n }\n}\n","/**\n * Reason phrases of the known HTTP status codes.\n * @see https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml\n */\nexport const httpStatusMessages: Record<number, string> = {\n 100: 'Continue',\n 101: 'Switching Protocols',\n 102: 'Processing',\n 103: 'Early Hints',\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 203: 'Non-Authoritative Information',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 207: 'Multi-Status',\n 208: 'Already Reported',\n 226: 'IM Used',\n 300: 'Multiple Choices',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 305: 'Use Proxy',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 407: 'Proxy Authentication Required',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 417: 'Expectation Failed',\n 418: \"I'm a Teapot\",\n 421: 'Misdirected Request',\n 422: 'Unprocessable Entity',\n 423: 'Locked',\n 424: 'Failed Dependency',\n 425: 'Too Early',\n 426: 'Upgrade Required',\n 428: 'Precondition Required',\n 429: 'Too Many Requests',\n 431: 'Request Header Fields Too Large',\n 451: 'Unavailable For Legal Reasons',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n 506: 'Variant Also Negotiates',\n 507: 'Insufficient Storage',\n 508: 'Loop Detected',\n 509: 'Bandwidth Limit Exceeded',\n 510: 'Not Extended',\n 511: 'Network Authentication Required',\n}\n","import type { HttpResponse, HttpResponseInit } from '#http/http-response'\nimport { httpStatusMessages } from './http-status-messages'\n\nconst kSetCookie = Symbol('kSetCookie')\n\nexport interface HttpResponseDecoratedInit extends HttpResponseInit {\n status: number\n statusText: string\n headers: Headers\n}\n\nexport function normalizeResponseInit(\n init: HttpResponseInit = {},\n): HttpResponseDecoratedInit {\n const status = init?.status || 200\n const statusText = init?.statusText || httpStatusMessages[status] || ''\n const headers = new Headers(init?.headers)\n\n return {\n ...init,\n headers,\n status,\n statusText,\n }\n}\n\nexport function decorateResponse(\n response: HttpResponse<any>,\n init: HttpResponseDecoratedInit,\n): Response {\n // Allow mocking the response type.\n if (init.type) {\n Object.defineProperty(response, 'type', {\n value: init.type,\n enumerable: true,\n writable: false,\n })\n }\n\n const responseCookies = init.headers.getSetCookie()\n\n if (responseCookies) {\n // Record the raw \"Set-Cookie\" response header provided\n // in the HeadersInit. This is later used to store these cookies\n // in cookie jar and return the right cookies in the \"cookies\"\n // response resolver argument.\n Object.defineProperty(response, kSetCookie, {\n value: responseCookies,\n enumerable: false,\n writable: false,\n })\n }\n\n return response\n}\n\nexport function getRawSetCookie(response: Response): Array<string> {\n return Reflect.get(response, kSetCookie) || []\n}\n\n/**\n * Copy the given response own properties, like internal symbols,\n * onto another response. Used for faithful internal copying of responses.\n */\nexport function copyResponseOwnProperties(\n source: Response,\n target: Response,\n): void {\n for (const propertyName of Reflect.ownKeys(source)) {\n const descriptor = Object.getOwnPropertyDescriptor(source, propertyName)\n const existingDescriptor = Object.getOwnPropertyDescriptor(\n target,\n propertyName,\n )\n\n if (descriptor && existingDescriptor == null) {\n Object.defineProperty(target, propertyName, descriptor)\n }\n }\n}\n","/**\n * Performs a case-insensitive comparison of two given strings.\n */\nexport function isStringEqual(actual: string, expected: string): boolean {\n return actual.toLowerCase() === expected.toLowerCase()\n}\n","interface GetTimestampOptions {\n milliseconds?: boolean\n}\n\n/**\n * Returns a timestamp string in a \"HH:MM:SS\" format.\n */\nexport function getTimestamp(options?: GetTimestampOptions): string {\n const now = new Date()\n const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`\n\n if (options?.milliseconds) {\n return `${timestamp}.${now.getMilliseconds().toString().padStart(3, '0')}`\n }\n\n return timestamp\n}\n","/**\n * Determines if the given URL string is an absolute URL.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url)\n}\n","import { isAbsoluteUrl } from './is-absolute-url'\n\n/**\n * Returns an absolute URL based on the given path.\n */\nexport function getAbsoluteUrl(path: string, baseUrl?: string): string {\n // already absolute URL\n if (isAbsoluteUrl(path)) {\n return path\n }\n\n // Ignore path with pattern start with *\n if (path.startsWith('*')) {\n return path\n }\n\n // Resolve a relative request URL against a given custom \"baseUrl\"\n // or the document baseURI (in the case of browser/browser-like environments).\n const origin = baseUrl || (typeof location !== 'undefined' && location.href)\n\n return origin\n ? // Encode and decode the path to preserve escaped characters.\n decodeURI(new URL(encodeURI(path), origin).href)\n : path\n}\n","import type { Path } from './match-request-url'\nimport { getCleanUrlString } from '#utils/get-clean-url-string'\nimport { getAbsoluteUrl } from '../url/get-absolute-url'\n\n/**\n * Normalizes a given request handler path:\n * - Preserves RegExp.\n * - Removes query parameters and hashes.\n * - Rebases relative URLs against the \"baseUrl\" or the current location.\n * - Preserves relative URLs in Node.js, unless specified otherwise.\n * - Preserves optional path parameters.\n */\nexport function normalizePath<ThisPath extends Path>(\n path: ThisPath,\n baseUrl?: string,\n): ThisPath {\n // RegExp paths do not need normalization.\n if (path instanceof RegExp) {\n return path\n }\n\n const maybeAbsoluteUrl = getAbsoluteUrl(path, baseUrl)\n\n return getCleanUrlString(maybeAbsoluteUrl) as ThisPath\n}\n","import { matchPattern } from '@msw/url'\nimport { getCleanUrl } from '@mswjs/interceptors'\nimport { normalizePath } from './normalize-path'\n\nexport type Path = string | RegExp\nexport type PathParams<KeyType extends keyof any = string> = {\n [ParamName in KeyType]?: string | ReadonlyArray<string>\n}\n\nexport interface Match {\n matches: boolean\n params?: PathParams\n}\n\nexport function isPath(value: unknown): value is Path {\n return typeof value === 'string' || value instanceof RegExp\n}\n\n/**\n * Match the given URL against a path pattern.\n */\nexport function matchRequestUrl(\n url: URL,\n pattern: Path,\n baseUrl?: string,\n): Match {\n const cleanUrl = getCleanUrl(url)\n\n if (pattern instanceof RegExp) {\n const match = pattern.flags.includes('g')\n ? [...cleanUrl.matchAll(pattern)].flat()\n : cleanUrl.match(pattern)\n\n return {\n matches: match != null && match.length > 0,\n params: Object.fromEntries(\n (match ?? []).slice(1).map((value, index) => [index, value]),\n ),\n }\n }\n\n // Resolve potentially realive patterns against the baseUrl.\n const normalizedPath = normalizePath(pattern, baseUrl)\n return matchPattern(normalizedPath, cleanUrl)\n}\n","/**\n * Returns a relative URL if the given request URL is relative\n * to the current origin. Otherwise returns an absolute URL.\n */\nexport function toPublicUrl(url: string | URL): string {\n const urlInstance = url instanceof URL ? url : new URL(url)\n\n if (\n typeof location !== 'undefined' &&\n urlInstance.origin === location.origin\n ) {\n return urlInstance.pathname\n }\n\n return urlInstance.origin + urlInstance.pathname\n}\n","/**\n * Parses a given value into a JSON.\n * Does not throw an exception on an invalid JSON string.\n */\nexport function jsonParse<ValueType extends Record<string, any>>(\n value: any,\n): ValueType | undefined {\n try {\n return JSON.parse(value)\n } catch {\n return undefined\n }\n}\n","import { isNodeProcess } from 'is-node-process'\nimport { invariant } from 'outvariant'\nimport {\n Cookie,\n CookieJar,\n MemoryCookieStore,\n type SerializedCookie,\n type MemoryCookieStoreIndex,\n} from 'tough-cookie'\nimport { jsonParse } from './internal/json-parse'\n\nclass CookieStore {\n #storageKey = '__msw-cookie-store__'\n #jar: CookieJar\n #memoryStore: MemoryCookieStore\n\n constructor() {\n invariant(\n typeof localStorage !== 'undefined',\n 'Failed to create a CookieStore: `localStorage` is not available in this environment. This is likely an issue with your environment, which has been detected as browser (or browser-like) environment and must implement global browser APIs correctly.',\n )\n\n this.#memoryStore = new MemoryCookieStore()\n this.#memoryStore.idx = this.getCookieStoreIndex()\n this.#jar = new CookieJar(this.#memoryStore)\n }\n\n public getCookies(url: string): Array<Cookie> {\n return this.#jar.getCookiesSync(url)\n }\n\n public async setCookie(cookieName: string, url: string): Promise<void> {\n await this.#jar.setCookie(cookieName, url)\n this.persist()\n }\n\n private getCookieStoreIndex(): MemoryCookieStoreIndex {\n if (\n typeof localStorage === 'undefined' ||\n typeof localStorage.getItem !== 'function'\n ) {\n return {}\n }\n\n const cookiesString = localStorage.getItem(this.#storageKey)\n if (cookiesString == null) {\n return {}\n }\n\n const rawCookies = jsonParse<Array<Record<string, unknown>>>(cookiesString)\n if (rawCookies == null) {\n return {}\n }\n\n const cookies: MemoryCookieStoreIndex = {}\n\n for (const rawCookie of rawCookies) {\n const cookie = Cookie.fromJSON(rawCookie)\n\n if (cookie != null && cookie.domain != null && cookie.path != null) {\n cookies[cookie.domain] ||= {}\n cookies[cookie.domain][cookie.path] ||= {}\n cookies[cookie.domain][cookie.path][cookie.key] = cookie\n }\n }\n\n return cookies\n }\n\n private persist(): void {\n if (\n typeof localStorage === 'undefined' ||\n typeof localStorage.setItem !== 'function'\n ) {\n return\n }\n\n const data: Array<SerializedCookie> = []\n const { idx } = this.#memoryStore\n\n for (const domain in idx) {\n for (const path in idx[domain]) {\n for (const key in idx[domain][path]) {\n data.push(idx[domain][path][key].toJSON())\n }\n }\n }\n\n try {\n localStorage.setItem(this.#storageKey, JSON.stringify(data))\n } catch {\n // Persisting cookies is best-effort. If the storage quota is exceeded,\n // keep the cookies in memory so the request handling continues.\n return\n }\n }\n}\n\n// Node.js has no implicit cookie jar. Leave cookie management to the client.\nexport const cookieStore = isNodeProcess() ? null : new CookieStore()\n"],"mappings":"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"}
@@ -1,15 +1,7 @@
1
- import { a as matchRequestUrl, f as httpStatusMessages, m as devUtils, r as toPublicUrl, s as getTimestamp, t as cookieStore } from "./cookie-store.js";
1
+ import { a as matchRequestUrl, c as isStringEqual, h as devUtils, p as httpStatusMessages, r as toPublicUrl, s as getTimestamp, t as cookieStore } from "./cookie-store.js";
2
2
  import { t as RequestHandler } from "./request-handler.js";
3
3
  import { getCleanUrlString } from "../utils/get-clean-url-string.js";
4
4
  import { parseCookie } from "cookie";
5
- //#region src/core/utils/internal/is-string-equal.ts
6
- /**
7
- * Performs a case-insensitive comparison of two given strings.
8
- */
9
- function isStringEqual(actual, expected) {
10
- return actual.toLowerCase() === expected.toLowerCase();
11
- }
12
- //#endregion
13
5
  //#region src/core/utils/logging/get-status-code-color.ts
14
6
  /**
15
7
  * Returns a HEX color for a given response status code number.
@@ -122,6 +114,19 @@ var HttpHandler = class extends RequestHandler {
122
114
  devUtils.warn(`Found a redundant usage of query parameters in the request handler URL for "${method} ${path}". Please match against a path instead and access query parameters using "new URL(request.url).searchParams" instead. Learn more: https://mswjs.io/docs/http/intercepting-requests#querysearch-parameters`);
123
115
  }
124
116
  async parse(args) {
117
+ /**
118
+ * @note CONNECT requests target an authority ("host:port"), not a URL.
119
+ * HTTP handlers never match them.
120
+ * @todo Match the authority against the handler path once
121
+ * `http.connect()` is supported instead of bailing out.
122
+ */
123
+ if (isStringEqual(args.request.method, "CONNECT")) return {
124
+ match: {
125
+ matches: false,
126
+ params: {}
127
+ },
128
+ cookies: {}
129
+ };
125
130
  const url = new URL(args.request.url);
126
131
  const cookies = getAllRequestCookies(args.request);
127
132
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"http-handler.js","names":[],"sources":["../../src/core/utils/internal/is-string-equal.ts","../../src/core/utils/logging/get-status-code-color.ts","../../src/core/utils/logging/serialize-request.ts","../../src/core/utils/logging/serialize-response.ts","../../src/core/utils/request/get-request-cookies.ts","../../src/http/http-handler.ts"],"sourcesContent":["/**\n * Performs a case-insensitive comparison of two given strings.\n */\nexport function isStringEqual(actual: string, expected: string): boolean {\n return actual.toLowerCase() === expected.toLowerCase()\n}\n","export enum StatusCodeColor {\n Success = '#69AB32',\n Warning = '#F0BB4B',\n Danger = '#E95F5D',\n}\n\n/**\n * Returns a HEX color for a given response status code number.\n */\nexport function getStatusCodeColor(status: number): StatusCodeColor {\n if (status < 300) {\n return StatusCodeColor.Success\n }\n\n if (status < 400) {\n return StatusCodeColor.Warning\n }\n\n return StatusCodeColor.Danger\n}\n","export interface LoggedRequest {\n url: URL\n method: string\n headers: Record<string, string>\n body: string\n}\n\n/**\n * Formats a mocked request for introspection in browser's console.\n */\nexport async function serializeRequest(\n request: Request,\n): Promise<LoggedRequest> {\n const requestClone = request.clone()\n const requestText = await requestClone.text()\n\n return {\n url: new URL(request.url),\n method: request.method,\n headers: Object.fromEntries(request.headers.entries()),\n body: requestText,\n }\n}\n","import { httpStatusMessages } from '../http-status-messages'\n\nexport interface SerializedResponse {\n status: number\n statusText: string\n headers: Record<string, any>\n body: string\n}\n\nexport async function serializeResponse(\n response: Response,\n): Promise<SerializedResponse> {\n const responseClone = response.clone()\n const responseText = await responseClone.text()\n\n // Normalize the response status and status text when logging\n // since the default Response instance doesn't infer status texts\n // from status codes. This has no effect on the actual response instance.\n const responseStatus = responseClone.status || 200\n const responseStatusText =\n responseClone.statusText || httpStatusMessages[responseStatus] || 'OK'\n\n return {\n status: responseStatus,\n statusText: responseStatusText,\n headers: Object.fromEntries(responseClone.headers.entries()),\n body: responseText,\n }\n}\n","import { parseCookie } from 'cookie'\nimport { cookieStore } from '../cookie-store'\n\nfunction parseCookies(input: string): Record<string, string> {\n const parsedCookies = parseCookie(input)\n const cookies: Record<string, string> = {}\n\n for (const cookieName in parsedCookies) {\n if (typeof parsedCookies[cookieName] !== 'undefined') {\n cookies[cookieName] = parsedCookies[cookieName]\n }\n }\n\n return cookies\n}\n\nfunction getAllDocumentCookies() {\n return parseCookies(document.cookie)\n}\n\n/**\n * Returns whether the given request would carry cookies,\n * based on its `credentials` mode.\n */\nfunction includesCredentials(request: Request): boolean {\n switch (request.credentials) {\n case 'same-origin': {\n // Include cookies only when requesting a resource\n // from the same origin as the current document.\n return (\n typeof location !== 'undefined' &&\n location.origin === new URL(request.url).origin\n )\n }\n\n case 'include': {\n return true\n }\n\n default: {\n return false\n }\n }\n}\n\nfunction getDocumentCookies(): Record<string, string> {\n if (typeof document === 'undefined') {\n return {}\n }\n\n return getAllDocumentCookies()\n}\n\nexport function getAllRequestCookies(request: Request): Record<string, string> {\n const requestCookieHeader = request.headers.get('cookie')\n const cookiesFromHeaders = requestCookieHeader\n ? parseCookies(requestCookieHeader)\n : {}\n\n if (cookieStore === null || !includesCredentials(request)) {\n return cookiesFromHeaders\n }\n\n const cookiesFromDocument = getDocumentCookies()\n\n const cookiesFromStore = cookieStore.getCookies(request.url)\n const storedCookiesObject = Object.fromEntries(\n cookiesFromStore.map((cookie) => [cookie.key, cookie.value]),\n )\n\n return {\n ...cookiesFromDocument,\n ...storedCookiesObject,\n ...cookiesFromHeaders,\n }\n}\n","import type { ResponseResolutionContext } from '#core/utils/execute-handlers'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport { isStringEqual } from '#core/utils/internal/is-string-equal'\nimport { getStatusCodeColor } from '#core/utils/logging/get-status-code-color'\nimport { getTimestamp } from '#core/utils/logging/get-timestamp'\nimport { serializeRequest } from '#core/utils/logging/serialize-request'\nimport { serializeResponse } from '#core/utils/logging/serialize-response'\nimport {\n matchRequestUrl,\n type Match,\n type Path,\n type PathParams,\n} from '#core/utils/matching/match-request-url'\nimport { toPublicUrl } from '#core/utils/request/to-public-url'\nimport { getAllRequestCookies } from '#core/utils/request/get-request-cookies'\nimport { getCleanUrlString } from '#utils/get-clean-url-string'\nimport {\n RequestHandler,\n type RequestHandlerDefaultInfo,\n type RequestHandlerOptions,\n type ResponseResolver,\n} from '#core/handlers/request-handler'\n\nexport type HttpHandlerMethod = string | RegExp\n\nexport interface HttpHandlerInfo extends RequestHandlerDefaultInfo {\n method: HttpHandlerMethod\n path: HttpRequestPredicate<PathParams>\n}\n\nexport enum HttpMethods {\n HEAD = 'HEAD',\n GET = 'GET',\n POST = 'POST',\n PUT = 'PUT',\n PATCH = 'PATCH',\n OPTIONS = 'OPTIONS',\n DELETE = 'DELETE',\n}\n\nexport type RequestQuery = {\n [queryName: string]: string\n}\n\nexport type HttpRequestParsedResult = {\n match: Match\n cookies: Record<string, string>\n}\n\nexport type HttpRequestResolverExtras<Params extends PathParams> = {\n params: Params\n cookies: Record<string, string>\n}\n\nexport type HttpCustomPredicate<Params extends PathParams> = (args: {\n request: Request\n cookies: Record<string, string>\n}) =>\n HttpCustomPredicateResult<Params> | Promise<HttpCustomPredicateResult<Params>>\n\ntype HttpCustomPredicateResult<Params extends PathParams> =\n | boolean\n | {\n matches: boolean\n params: Params\n }\n\nexport type HttpRequestPredicate<Params extends PathParams> =\n Path | HttpCustomPredicate<Params>\n\n/**\n * Request handler for HTTP requests.\n * Provides request matching based on method and URL.\n */\nexport class HttpHandler extends RequestHandler<\n HttpHandlerInfo,\n HttpRequestParsedResult,\n HttpRequestResolverExtras<any>\n> {\n constructor(\n method: HttpHandlerMethod,\n predicate: HttpRequestPredicate<PathParams>,\n resolver: ResponseResolver<HttpRequestResolverExtras<any>, any, any>,\n options?: RequestHandlerOptions,\n ) {\n const displayPath =\n typeof predicate === 'function' ? '[custom predicate]' : predicate\n\n super({\n info: {\n header: `${method}${displayPath ? ` ${displayPath}` : ''}`,\n path: predicate,\n method,\n },\n resolver,\n options,\n })\n\n this.checkRedundantQueryParameters()\n }\n\n private checkRedundantQueryParameters() {\n const { method, path } = this.info\n\n if (!path || path instanceof RegExp || typeof path === 'function') {\n return\n }\n\n const url = getCleanUrlString(path)\n\n // Bypass request handler URLs that have no redundant characters.\n if (url === path) {\n return\n }\n\n devUtils.warn(\n `Found a redundant usage of query parameters in the request handler URL for \"${method} ${path}\". Please match against a path instead and access query parameters using \"new URL(request.url).searchParams\" instead. Learn more: https://mswjs.io/docs/http/intercepting-requests#querysearch-parameters`,\n )\n }\n\n async parse(args: {\n request: Request\n resolutionContext?: ResponseResolutionContext\n }) {\n const url = new URL(args.request.url)\n const cookies = getAllRequestCookies(args.request)\n\n /**\n * Handle custom predicate functions.\n * @note Invoke this during parsing so the user can parse the path parameters\n * manually. Otherwise, `params` is always an empty object, which isn't nice.\n */\n if (typeof this.info.path === 'function') {\n const customPredicateResult = await this.info.path({\n request: args.request,\n cookies,\n })\n\n const match =\n typeof customPredicateResult === 'boolean'\n ? {\n matches: customPredicateResult,\n params: {},\n }\n : customPredicateResult\n\n return {\n match,\n cookies,\n }\n }\n\n const match = this.info.path\n ? matchRequestUrl(url, this.info.path, args.resolutionContext?.baseUrl)\n : { matches: false, params: {} }\n\n return {\n match,\n cookies,\n }\n }\n\n async predicate(args: {\n request: Request\n parsedResult: HttpRequestParsedResult\n resolutionContext?: ResponseResolutionContext\n }) {\n const hasMatchingMethod = this.matchMethod(args.request.method)\n const hasMatchingUrl = args.parsedResult.match.matches\n return hasMatchingMethod && hasMatchingUrl\n }\n\n private matchMethod(actualMethod: string): boolean {\n return this.info.method instanceof RegExp\n ? this.info.method.test(actualMethod)\n : isStringEqual(this.info.method, actualMethod)\n }\n\n protected extendResolverArgs(args: {\n request: Request\n parsedResult: HttpRequestParsedResult\n }) {\n return {\n params: args.parsedResult.match?.params || {},\n cookies: args.parsedResult.cookies,\n }\n }\n\n async log(args: { request: Request; response: Response }) {\n const publicUrl = toPublicUrl(args.request.url)\n const loggedRequest = await serializeRequest(args.request)\n const loggedResponse = await serializeResponse(args.response)\n const statusColor = getStatusCodeColor(loggedResponse.status)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp()} ${args.request.method} ${publicUrl} (%c${\n loggedResponse.status\n } ${loggedResponse.statusText}%c)`,\n ),\n `color:${statusColor}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log('Request', loggedRequest)\n // eslint-disable-next-line no-console\n console.log('Handler:', this)\n // eslint-disable-next-line no-console\n console.log('Response', loggedResponse)\n console.groupEnd()\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"http-handler.js","names":[],"sources":["../../src/core/utils/logging/get-status-code-color.ts","../../src/core/utils/logging/serialize-request.ts","../../src/core/utils/logging/serialize-response.ts","../../src/core/utils/request/get-request-cookies.ts","../../src/http/http-handler.ts"],"sourcesContent":["export enum StatusCodeColor {\n Success = '#69AB32',\n Warning = '#F0BB4B',\n Danger = '#E95F5D',\n}\n\n/**\n * Returns a HEX color for a given response status code number.\n */\nexport function getStatusCodeColor(status: number): StatusCodeColor {\n if (status < 300) {\n return StatusCodeColor.Success\n }\n\n if (status < 400) {\n return StatusCodeColor.Warning\n }\n\n return StatusCodeColor.Danger\n}\n","export interface LoggedRequest {\n url: URL\n method: string\n headers: Record<string, string>\n body: string\n}\n\n/**\n * Formats a mocked request for introspection in browser's console.\n */\nexport async function serializeRequest(\n request: Request,\n): Promise<LoggedRequest> {\n const requestClone = request.clone()\n const requestText = await requestClone.text()\n\n return {\n url: new URL(request.url),\n method: request.method,\n headers: Object.fromEntries(request.headers.entries()),\n body: requestText,\n }\n}\n","import { httpStatusMessages } from '../http-status-messages'\n\nexport interface SerializedResponse {\n status: number\n statusText: string\n headers: Record<string, any>\n body: string\n}\n\nexport async function serializeResponse(\n response: Response,\n): Promise<SerializedResponse> {\n const responseClone = response.clone()\n const responseText = await responseClone.text()\n\n // Normalize the response status and status text when logging\n // since the default Response instance doesn't infer status texts\n // from status codes. This has no effect on the actual response instance.\n const responseStatus = responseClone.status || 200\n const responseStatusText =\n responseClone.statusText || httpStatusMessages[responseStatus] || 'OK'\n\n return {\n status: responseStatus,\n statusText: responseStatusText,\n headers: Object.fromEntries(responseClone.headers.entries()),\n body: responseText,\n }\n}\n","import { parseCookie } from 'cookie'\nimport { cookieStore } from '../cookie-store'\n\nfunction parseCookies(input: string): Record<string, string> {\n const parsedCookies = parseCookie(input)\n const cookies: Record<string, string> = {}\n\n for (const cookieName in parsedCookies) {\n if (typeof parsedCookies[cookieName] !== 'undefined') {\n cookies[cookieName] = parsedCookies[cookieName]\n }\n }\n\n return cookies\n}\n\nfunction getAllDocumentCookies() {\n return parseCookies(document.cookie)\n}\n\n/**\n * Returns whether the given request would carry cookies,\n * based on its `credentials` mode.\n */\nfunction includesCredentials(request: Request): boolean {\n switch (request.credentials) {\n case 'same-origin': {\n // Include cookies only when requesting a resource\n // from the same origin as the current document.\n return (\n typeof location !== 'undefined' &&\n location.origin === new URL(request.url).origin\n )\n }\n\n case 'include': {\n return true\n }\n\n default: {\n return false\n }\n }\n}\n\nfunction getDocumentCookies(): Record<string, string> {\n if (typeof document === 'undefined') {\n return {}\n }\n\n return getAllDocumentCookies()\n}\n\nexport function getAllRequestCookies(request: Request): Record<string, string> {\n const requestCookieHeader = request.headers.get('cookie')\n const cookiesFromHeaders = requestCookieHeader\n ? parseCookies(requestCookieHeader)\n : {}\n\n if (cookieStore === null || !includesCredentials(request)) {\n return cookiesFromHeaders\n }\n\n const cookiesFromDocument = getDocumentCookies()\n\n const cookiesFromStore = cookieStore.getCookies(request.url)\n const storedCookiesObject = Object.fromEntries(\n cookiesFromStore.map((cookie) => [cookie.key, cookie.value]),\n )\n\n return {\n ...cookiesFromDocument,\n ...storedCookiesObject,\n ...cookiesFromHeaders,\n }\n}\n","import type { ResponseResolutionContext } from '#core/utils/execute-handlers'\nimport { devUtils } from '#core/utils/internal/dev-utils'\nimport { isStringEqual } from '#core/utils/internal/is-string-equal'\nimport { getStatusCodeColor } from '#core/utils/logging/get-status-code-color'\nimport { getTimestamp } from '#core/utils/logging/get-timestamp'\nimport { serializeRequest } from '#core/utils/logging/serialize-request'\nimport { serializeResponse } from '#core/utils/logging/serialize-response'\nimport {\n matchRequestUrl,\n type Match,\n type Path,\n type PathParams,\n} from '#core/utils/matching/match-request-url'\nimport { toPublicUrl } from '#core/utils/request/to-public-url'\nimport { getAllRequestCookies } from '#core/utils/request/get-request-cookies'\nimport { getCleanUrlString } from '#utils/get-clean-url-string'\nimport {\n RequestHandler,\n type RequestHandlerDefaultInfo,\n type RequestHandlerOptions,\n type ResponseResolver,\n} from '#core/handlers/request-handler'\n\nexport type HttpHandlerMethod = string | RegExp\n\nexport interface HttpHandlerInfo extends RequestHandlerDefaultInfo {\n method: HttpHandlerMethod\n path: HttpRequestPredicate<PathParams>\n}\n\nexport enum HttpMethods {\n HEAD = 'HEAD',\n GET = 'GET',\n POST = 'POST',\n PUT = 'PUT',\n PATCH = 'PATCH',\n OPTIONS = 'OPTIONS',\n DELETE = 'DELETE',\n}\n\nexport type RequestQuery = {\n [queryName: string]: string\n}\n\nexport type HttpRequestParsedResult = {\n match: Match\n cookies: Record<string, string>\n}\n\nexport type HttpRequestResolverExtras<Params extends PathParams> = {\n params: Params\n cookies: Record<string, string>\n}\n\nexport type HttpCustomPredicate<Params extends PathParams> = (args: {\n request: Request\n cookies: Record<string, string>\n}) =>\n HttpCustomPredicateResult<Params> | Promise<HttpCustomPredicateResult<Params>>\n\ntype HttpCustomPredicateResult<Params extends PathParams> =\n | boolean\n | {\n matches: boolean\n params: Params\n }\n\nexport type HttpRequestPredicate<Params extends PathParams> =\n Path | HttpCustomPredicate<Params>\n\n/**\n * Request handler for HTTP requests.\n * Provides request matching based on method and URL.\n */\nexport class HttpHandler extends RequestHandler<\n HttpHandlerInfo,\n HttpRequestParsedResult,\n HttpRequestResolverExtras<any>\n> {\n constructor(\n method: HttpHandlerMethod,\n predicate: HttpRequestPredicate<PathParams>,\n resolver: ResponseResolver<HttpRequestResolverExtras<any>, any, any>,\n options?: RequestHandlerOptions,\n ) {\n const displayPath =\n typeof predicate === 'function' ? '[custom predicate]' : predicate\n\n super({\n info: {\n header: `${method}${displayPath ? ` ${displayPath}` : ''}`,\n path: predicate,\n method,\n },\n resolver,\n options,\n })\n\n this.checkRedundantQueryParameters()\n }\n\n private checkRedundantQueryParameters() {\n const { method, path } = this.info\n\n if (!path || path instanceof RegExp || typeof path === 'function') {\n return\n }\n\n const url = getCleanUrlString(path)\n\n // Bypass request handler URLs that have no redundant characters.\n if (url === path) {\n return\n }\n\n devUtils.warn(\n `Found a redundant usage of query parameters in the request handler URL for \"${method} ${path}\". Please match against a path instead and access query parameters using \"new URL(request.url).searchParams\" instead. Learn more: https://mswjs.io/docs/http/intercepting-requests#querysearch-parameters`,\n )\n }\n\n async parse(args: {\n request: Request\n resolutionContext?: ResponseResolutionContext\n }) {\n /**\n * @note CONNECT requests target an authority (\"host:port\"), not a URL.\n * HTTP handlers never match them.\n * @todo Match the authority against the handler path once\n * `http.connect()` is supported instead of bailing out.\n */\n if (isStringEqual(args.request.method, 'CONNECT')) {\n return {\n match: { matches: false, params: {} },\n cookies: {},\n }\n }\n\n const url = new URL(args.request.url)\n const cookies = getAllRequestCookies(args.request)\n\n /**\n * Handle custom predicate functions.\n * @note Invoke this during parsing so the user can parse the path parameters\n * manually. Otherwise, `params` is always an empty object, which isn't nice.\n */\n if (typeof this.info.path === 'function') {\n const customPredicateResult = await this.info.path({\n request: args.request,\n cookies,\n })\n\n const match =\n typeof customPredicateResult === 'boolean'\n ? {\n matches: customPredicateResult,\n params: {},\n }\n : customPredicateResult\n\n return {\n match,\n cookies,\n }\n }\n\n const match = this.info.path\n ? matchRequestUrl(url, this.info.path, args.resolutionContext?.baseUrl)\n : { matches: false, params: {} }\n\n return {\n match,\n cookies,\n }\n }\n\n async predicate(args: {\n request: Request\n parsedResult: HttpRequestParsedResult\n resolutionContext?: ResponseResolutionContext\n }) {\n const hasMatchingMethod = this.matchMethod(args.request.method)\n const hasMatchingUrl = args.parsedResult.match.matches\n return hasMatchingMethod && hasMatchingUrl\n }\n\n private matchMethod(actualMethod: string): boolean {\n return this.info.method instanceof RegExp\n ? this.info.method.test(actualMethod)\n : isStringEqual(this.info.method, actualMethod)\n }\n\n protected extendResolverArgs(args: {\n request: Request\n parsedResult: HttpRequestParsedResult\n }) {\n return {\n params: args.parsedResult.match?.params || {},\n cookies: args.parsedResult.cookies,\n }\n }\n\n async log(args: { request: Request; response: Response }) {\n const publicUrl = toPublicUrl(args.request.url)\n const loggedRequest = await serializeRequest(args.request)\n const loggedResponse = await serializeResponse(args.response)\n const statusColor = getStatusCodeColor(loggedResponse.status)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp()} ${args.request.method} ${publicUrl} (%c${\n loggedResponse.status\n } ${loggedResponse.statusText}%c)`,\n ),\n `color:${statusColor}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log('Request', loggedRequest)\n // eslint-disable-next-line no-console\n console.log('Handler:', this)\n // eslint-disable-next-line no-console\n console.log('Response', loggedResponse)\n console.groupEnd()\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { d as normalizeResponseInit, l as decorateResponse } from "./cookie-store.js";
1
+ import { f as normalizeResponseInit, u as decorateResponse } from "./cookie-store.js";
2
2
  import { n as kDefaultContentType, t as bodyType } from "./symbols.js";
3
3
  import { FetchResponse } from "@mswjs/interceptors";
4
4
  //#region src/http/http-response.ts
@@ -1,4 +1,4 @@
1
- import { m as devUtils, p as InternalError, r as toPublicUrl, t as cookieStore, u as getRawSetCookie } from "./cookie-store.js";
1
+ import { c as isStringEqual, d as getRawSetCookie, h as devUtils, m as InternalError, r as toPublicUrl, t as cookieStore } from "./cookie-store.js";
2
2
  import { n as getSiblingHandlers, o as kAutoConnect, r as isSiblingHandler, s as kConnect } from "./attach-sibling-handlers.js";
3
3
  import { t as executeHandlers } from "./execute-handlers.js";
4
4
  import { isPassthroughResponse } from "../utils/passthrough.js";
@@ -459,6 +459,20 @@ var HttpNetworkFrame = class extends NetworkFrame {
459
459
  return null;
460
460
  }
461
461
  if (lookupResult == null) {
462
+ /**
463
+ * @note Unhandled CONNECT requests establish a tunnel through a proxy.
464
+ * They are transport, not the request the developer cares about, so
465
+ * they pass through silently regardless of the unhandled frame strategy.
466
+ * The request sent through the tunnel gets its own resolution.
467
+ */
468
+ if (isStringEqual(request.method, "CONNECT")) {
469
+ this.events.emit(new RequestEvent("request:end", {
470
+ requestId,
471
+ request
472
+ }));
473
+ this.passthrough();
474
+ return null;
475
+ }
462
476
  this.events.emit(new RequestEvent("request:unhandled", {
463
477
  requestId,
464
478
  request