msw 3.0.2 → 3.0.4
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 +51 -35
- package/lib/_chunks/cookie-store.js +3 -2
- package/lib/_chunks/cookie-store.js.map +1 -1
- package/lib/_chunks/interceptor-source.d.ts +5 -1
- package/lib/_chunks/interceptor-source.js +18 -5
- package/lib/_chunks/interceptor-source.js.map +1 -1
- package/lib/_chunks/request-handler.d.ts +3 -2
- package/lib/browser/index.d.ts +4 -9
- package/lib/browser/index.js +22 -15
- package/lib/browser/index.js.map +1 -1
- package/lib/graphql/index.d.ts +19 -4
- package/lib/graphql/index.js +24 -12
- package/lib/graphql/index.js.map +1 -1
- package/lib/iife/index.js +68 -35
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +152 -12
- package/lib/utils/is-common-asset-request.js +1 -1
- package/lib/utils/is-common-asset-request.js.map +1 -1
- package/package.json +2 -3
- package/src/browser/default-network-options.ts +1 -1
- package/src/browser/setup-worker.ts +1 -4
- package/src/browser/sources/fallback-http-source.ts +11 -8
- package/src/browser/sources/service-worker-source.ts +12 -5
- package/src/browser/utils/should-invalidate-worker.test.ts +0 -16
- package/src/core/experimental/define-network.ts +1 -1
- package/src/core/experimental/handlers-controller.test.ts +61 -0
- package/src/core/experimental/handlers-controller.ts +39 -6
- package/src/core/experimental/sources/network-source.ts +8 -1
- package/src/core/handlers/handler.ts +3 -2
- package/src/graphql/graphql-subscription.ts +30 -12
- package/src/mockServiceWorker.js +150 -10
- package/src/utils/is-common-asset-request.test.ts +371 -0
- package/src/utils/is-common-asset-request.ts +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
<a href="https://kettanaito.com/discord" target="_blank">Join our Discord server</a>
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
|
-
<br />
|
|
13
12
|
<br />
|
|
14
13
|
|
|
15
14
|
## Features
|
|
@@ -146,6 +145,35 @@ app.get(
|
|
|
146
145
|
|
|
147
146
|
> This example showcases [`server.boundary()`](https://mswjs.io/docs/api/setup-server/boundary) to scope request interception to a particular closure, which is extremely handy!
|
|
148
147
|
|
|
148
|
+
## Partners
|
|
149
|
+
|
|
150
|
+
Active development and maintenance of MSW is made possible with the help from our incredible partners:
|
|
151
|
+
|
|
152
|
+
<table>
|
|
153
|
+
<tr>
|
|
154
|
+
<td align="center">
|
|
155
|
+
<a href="https://www.beehiiv.com/?ref=mswjs" target="_blank">
|
|
156
|
+
<img src="media/partners/beehiiv.svg" alt="Beehiiv" width="150" />
|
|
157
|
+
</a>
|
|
158
|
+
</td>
|
|
159
|
+
<td align="center">
|
|
160
|
+
<a href="https://www.chromatic.com/?ref=mswjs" target="_blank">
|
|
161
|
+
<img src="media/partners/chromatic.svg" alt="Chromatic" height="64" />
|
|
162
|
+
</a>
|
|
163
|
+
</td>
|
|
164
|
+
<td align="center">
|
|
165
|
+
<a href="https://coderabbit.link/mswjs" target="_blank">
|
|
166
|
+
<img src="media/partners/coderabbit.svg" alt="CodeRabbit" width="150" />
|
|
167
|
+
</a>
|
|
168
|
+
</td>
|
|
169
|
+
<td align="center">
|
|
170
|
+
<a href="https://workleap.com/?ref=mswjs" target="_blank">
|
|
171
|
+
<img src="media/partners/workleap.svg" alt="Workleap" width="150" />
|
|
172
|
+
</a>
|
|
173
|
+
</td>
|
|
174
|
+
</tr>
|
|
175
|
+
</table>
|
|
176
|
+
|
|
149
177
|
## Sponsors
|
|
150
178
|
|
|
151
179
|
Mock Service Worker is trusted by hundreds of thousands of engineers around the globe. It's used by companies like Google, Microsoft, Spotify, Amazon, Netflix, and countless others. Despite that, it remains a hobby project maintained in a spare time and has no opportunity to financially support even a single full-time contributor.
|
|
@@ -162,7 +190,7 @@ Mock Service Worker is trusted by hundreds of thousands of engineers around the
|
|
|
162
190
|
|
|
163
191
|
<table>
|
|
164
192
|
<tr>
|
|
165
|
-
<td>
|
|
193
|
+
<td align="center">
|
|
166
194
|
<a href="https://www.github.com/" target="_blank">
|
|
167
195
|
<picture>
|
|
168
196
|
<source media="(prefers-color-scheme: dark)" srcset="media/sponsors/github-light.svg" />
|
|
@@ -170,28 +198,11 @@ Mock Service Worker is trusted by hundreds of thousands of engineers around the
|
|
|
170
198
|
</picture>
|
|
171
199
|
</a>
|
|
172
200
|
</td>
|
|
173
|
-
<td>
|
|
174
|
-
<a href="https://workleap.com/" target="_blank">
|
|
175
|
-
<img src="media/sponsors/workleap.svg" alt="Workleap" height="64" width="174" />
|
|
176
|
-
</a>
|
|
177
|
-
</td>
|
|
178
|
-
<td>
|
|
179
|
-
<a href="https://www.chromatic.com/?ref=mswjs" target="_blank">
|
|
180
|
-
<img src="media/sponsors/chromatic.svg" alt="Chromatic" height="64" />
|
|
181
|
-
</a>
|
|
182
|
-
</td>
|
|
183
|
-
</tr>
|
|
184
|
-
<tr>
|
|
185
201
|
<td align="center">
|
|
186
202
|
<a href="https://stackblitz.com/" target="_blank">
|
|
187
203
|
<img src="media/sponsors/stackblitz.svg" alt="StackBlitz" height="64" />
|
|
188
204
|
</a>
|
|
189
205
|
</td>
|
|
190
|
-
<td align="center">
|
|
191
|
-
<a href="https://coderabbit.link/mswjs" target="_blank">
|
|
192
|
-
<img src="media/sponsors/coderabbit.svg" alt="CodeRabbit" height="64" />
|
|
193
|
-
</a>
|
|
194
|
-
</td>
|
|
195
206
|
</tr>
|
|
196
207
|
</table>
|
|
197
208
|
|
|
@@ -205,21 +216,36 @@ Mock Service Worker is trusted by hundreds of thousands of engineers around the
|
|
|
205
216
|
|
|
206
217
|
<table>
|
|
207
218
|
<tr>
|
|
208
|
-
<td>
|
|
219
|
+
<td align="center">
|
|
209
220
|
<a href="https://www.replay.io/" target="_blank">
|
|
210
221
|
<img src="media/sponsors/replay.svg" alt="Replay" height="64" />
|
|
211
222
|
</a>
|
|
212
223
|
</td>
|
|
213
|
-
<td>
|
|
224
|
+
<td align="center">
|
|
214
225
|
<a href="https://codemod.com/" target="_blank">
|
|
215
226
|
<img src="media/sponsors/codemod.svg" alt="Codemod" height="64" width="128" />
|
|
216
227
|
</a>
|
|
217
228
|
</td>
|
|
218
|
-
<td>
|
|
229
|
+
<td align="center">
|
|
219
230
|
<a href="https://github.com/ryanmagoon" target="_blank">
|
|
220
231
|
<img src="https://github.com/ryanmagoon.png" alt="Ryan Magoon" height="64" />
|
|
221
232
|
</a>
|
|
222
233
|
</td>
|
|
234
|
+
<td align="center">
|
|
235
|
+
<a href="https://kraken.tech/" target="_blank">
|
|
236
|
+
<img src="media/sponsors/kraken-tech.svg" alt="Kraken Tech" width="150" />
|
|
237
|
+
</a>
|
|
238
|
+
</td>
|
|
239
|
+
<td align="center">
|
|
240
|
+
<a href="https://currents.dev/" target="_blank">
|
|
241
|
+
<img src="media/sponsors/currents.svg" alt="Currents" width="150" />
|
|
242
|
+
</a>
|
|
243
|
+
</td>
|
|
244
|
+
<td align="center">
|
|
245
|
+
<a href="https://github.com/ryota-murakami" target="_blank">
|
|
246
|
+
<img src="https://github.com/ryota-murakami.png" alt="Ryota Murakami" height="64" />
|
|
247
|
+
</a>
|
|
248
|
+
</td>
|
|
223
249
|
</tr>
|
|
224
250
|
</table>
|
|
225
251
|
|
|
@@ -233,21 +259,11 @@ Mock Service Worker is trusted by hundreds of thousands of engineers around the
|
|
|
233
259
|
|
|
234
260
|
<table>
|
|
235
261
|
<tr>
|
|
236
|
-
<td>
|
|
262
|
+
<td align="center">
|
|
237
263
|
<a href="https://materialize.com/" target="_blank">
|
|
238
264
|
<img src="media/sponsors/materialize.svg" alt="Materialize" height="64" />
|
|
239
265
|
</a>
|
|
240
266
|
</td>
|
|
241
|
-
<td>
|
|
242
|
-
<a href="https://trigger.dev/" target="_blank">
|
|
243
|
-
<img src="media/sponsors/trigger-dev.png" alt="Trigger.dev" height="64" />
|
|
244
|
-
</a>
|
|
245
|
-
</td>
|
|
246
|
-
<td>
|
|
247
|
-
<a href="https://vital.io/" target="_blank">
|
|
248
|
-
<img src="media/sponsors/vital.svg" alt="Vital" width="64" />
|
|
249
|
-
</a>
|
|
250
|
-
</td>
|
|
251
267
|
</tr>
|
|
252
268
|
</table>
|
|
253
269
|
|
|
@@ -260,7 +276,7 @@ We've been extremely humbled to receive awards and mentions from the community f
|
|
|
260
276
|
<td width="124">
|
|
261
277
|
<img src="https://raw.githubusercontent.com/mswjs/msw/main/media/tech-radar.png" width="124" alt="Technology Radar">
|
|
262
278
|
</td>
|
|
263
|
-
<td>
|
|
279
|
+
<td align="center">
|
|
264
280
|
<h4>Solution Worth Pursuing</h4>
|
|
265
281
|
<p><em><a href="https://www.thoughtworks.com/radar/languages-and-frameworks/mock-service-worker">Technology Radar</a> (2020–2021)</em></p>
|
|
266
282
|
</td>
|
|
@@ -269,7 +285,7 @@ We've been extremely humbled to receive awards and mentions from the community f
|
|
|
269
285
|
<td width="124">
|
|
270
286
|
<img src="https://raw.githubusercontent.com/mswjs/msw/main/media/os-awards.png" width="124" alt="Open Source Awards 2020">
|
|
271
287
|
</td>
|
|
272
|
-
<td>
|
|
288
|
+
<td align="center">
|
|
273
289
|
<h4>The Most Exciting Use of Technology</h4>
|
|
274
290
|
<p><em><a href="https://osawards.com/javascript/2020">Open Source Awards</a> (2020)</em></p>
|
|
275
291
|
</td>
|
|
@@ -28,8 +28,9 @@ var Handler = class {
|
|
|
28
28
|
/**
|
|
29
29
|
* Release the resources held by this handler.
|
|
30
30
|
*
|
|
31
|
-
* @note This method is invoked automatically when the
|
|
32
|
-
* disabled (e.g. `server.close()`)
|
|
31
|
+
* @note This method is invoked automatically when the handler leaves
|
|
32
|
+
* the network: when the network is disabled (e.g. `server.close()`)
|
|
33
|
+
* or when a reset removes it (e.g. `server.resetHandlers()`). Override it in the handlers that
|
|
33
34
|
* hold onto anything beyond a single frame, like timers, connections,
|
|
34
35
|
* or event listeners. Returning a promise makes the network await
|
|
35
36
|
* this handler's disposal before it tears itself down.
|
|
@@ -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/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
|
+
{"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 handler leaves\n * the network: when the network is disabled (e.g. `server.close()`)\n * or when a reset removes it (e.g. `server.resetHandlers()`). 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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"}
|
|
@@ -79,7 +79,11 @@ type ExtractSourceEvents<Source> = Source extends NetworkSource<infer Frame> ? E
|
|
|
79
79
|
declare abstract class NetworkSource<Frame extends AnyNetworkFrame = AnyNetworkFrame> {
|
|
80
80
|
protected emitter: Emitter<NetworkSourceEventMap<Frame>>;
|
|
81
81
|
constructor();
|
|
82
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Enable this network source.
|
|
84
|
+
* @param context The resolved context of the network this source belongs to.
|
|
85
|
+
*/
|
|
86
|
+
abstract enable(context?: NetworkFrameResolutionContext): unknown | Promise<unknown>;
|
|
83
87
|
queue(frame: Frame): Promise<void>;
|
|
84
88
|
on<Type extends keyof NetworkSourceEventMap<Frame>>(type: Type, listener: Emitter.Listener<typeof this.emitter, Type>, options?: TypedListenerOptions): void;
|
|
85
89
|
disable(): void | Promise<void>;
|
|
@@ -93,16 +93,26 @@ var HandlersController = class {
|
|
|
93
93
|
}
|
|
94
94
|
reset(nextHandlers) {
|
|
95
95
|
invariant(nextHandlers.length > 0 ? this.#validateHandlers(nextHandlers) : true, devUtils.formatMessage("Failed to replace initial handlers during reset: invalid handlers. Did you forget to spread the handlers array?"));
|
|
96
|
-
for (const handler of this.currentHandlers()) handler.reset();
|
|
97
96
|
const { initialHandlers } = this.getState();
|
|
97
|
+
const nextInitialHandlers = nextHandlers.length > 0 ? groupHandlersByKind(nextHandlers) : initialHandlers;
|
|
98
|
+
const currentHandlers = new Set(this.currentHandlers());
|
|
99
|
+
const nextHandlersSet = new Set(Object.values(nextInitialHandlers).flat().filter(Boolean));
|
|
100
|
+
for (const handler of currentHandlers.intersection(nextHandlersSet)) handler.reset();
|
|
101
|
+
for (const handler of currentHandlers.difference(nextHandlersSet)) try {
|
|
102
|
+
const disposal = handler.dispose();
|
|
103
|
+
if (disposal instanceof Promise) disposal.catch((error) => {
|
|
104
|
+
this.#printDisposalError(handler, error);
|
|
105
|
+
});
|
|
106
|
+
} catch (error) {
|
|
107
|
+
this.#printDisposalError(handler, error);
|
|
108
|
+
}
|
|
98
109
|
if (nextHandlers.length === 0) {
|
|
99
110
|
this.setState({ handlers: { ...initialHandlers } });
|
|
100
111
|
return;
|
|
101
112
|
}
|
|
102
|
-
const normalizedNextHandlers = groupHandlersByKind(nextHandlers);
|
|
103
113
|
this.setState({
|
|
104
|
-
initialHandlers:
|
|
105
|
-
handlers: { ...
|
|
114
|
+
initialHandlers: nextInitialHandlers,
|
|
115
|
+
handlers: { ...nextInitialHandlers }
|
|
106
116
|
});
|
|
107
117
|
}
|
|
108
118
|
restore() {
|
|
@@ -119,6 +129,9 @@ var HandlersController = class {
|
|
|
119
129
|
#validateHandlers(handlers) {
|
|
120
130
|
return handlers.every((handler) => !Array.isArray(handler));
|
|
121
131
|
}
|
|
132
|
+
#printDisposalError(handler, error) {
|
|
133
|
+
devUtils.error("Failed to dispose of \"%s\" handler removed during reset. Please see the original error below.\n%s", handler.kind, error);
|
|
134
|
+
}
|
|
122
135
|
};
|
|
123
136
|
var InMemoryHandlersController = class extends HandlersController {
|
|
124
137
|
#handlers;
|
|
@@ -250,7 +263,7 @@ function defineNetwork(options) {
|
|
|
250
263
|
const handlers = frame.getHandlers(handlersController);
|
|
251
264
|
await frame.resolve(handlers, resolvedOptions.onUnhandledFrame || "warn", resolvedOptions.context);
|
|
252
265
|
});
|
|
253
|
-
return source.enable();
|
|
266
|
+
return source.enable(resolvedOptions.context);
|
|
254
267
|
}));
|
|
255
268
|
},
|
|
256
269
|
disable() {
|