msw 2.3.0-ws.rc-5 → 2.3.0-ws.rc-7
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 +3 -9
- package/lib/browser/index.js +160 -62
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/index.mjs +160 -62
- package/lib/browser/index.mjs.map +1 -1
- package/lib/core/handlers/WebSocketHandler.js +1 -2
- package/lib/core/handlers/WebSocketHandler.js.map +1 -1
- package/lib/core/handlers/WebSocketHandler.mjs +1 -2
- package/lib/core/handlers/WebSocketHandler.mjs.map +1 -1
- package/lib/core/utils/internal/Disposable.d.mts +2 -2
- package/lib/core/utils/internal/Disposable.d.ts +2 -2
- package/lib/core/utils/internal/Disposable.js +5 -2
- package/lib/core/utils/internal/Disposable.js.map +1 -1
- package/lib/core/utils/internal/Disposable.mjs +5 -2
- package/lib/core/utils/internal/Disposable.mjs.map +1 -1
- package/lib/core/utils/internal/devUtils.d.mts +10 -1
- package/lib/core/utils/internal/devUtils.d.ts +10 -1
- package/lib/core/utils/internal/devUtils.js +7 -0
- package/lib/core/utils/internal/devUtils.js.map +1 -1
- package/lib/core/utils/internal/devUtils.mjs +7 -0
- package/lib/core/utils/internal/devUtils.mjs.map +1 -1
- package/lib/core/utils/matching/normalizePath.d.mts +1 -0
- package/lib/core/utils/matching/normalizePath.d.ts +1 -0
- package/lib/core/utils/matching/normalizePath.js.map +1 -1
- package/lib/core/utils/matching/normalizePath.mjs.map +1 -1
- package/lib/core/utils/request/onUnhandledRequest.js +3 -3
- package/lib/core/utils/request/onUnhandledRequest.js.map +1 -1
- package/lib/core/utils/request/onUnhandledRequest.mjs +4 -4
- package/lib/core/utils/request/onUnhandledRequest.mjs.map +1 -1
- package/lib/core/utils/url/cleanUrl.d.mts +2 -1
- package/lib/core/utils/url/cleanUrl.d.ts +2 -1
- package/lib/core/utils/url/cleanUrl.js +3 -0
- package/lib/core/utils/url/cleanUrl.js.map +1 -1
- package/lib/core/utils/url/cleanUrl.mjs +3 -0
- package/lib/core/utils/url/cleanUrl.mjs.map +1 -1
- package/lib/core/ws/WebSocketClientManager.d.mts +9 -15
- package/lib/core/ws/WebSocketClientManager.d.ts +9 -15
- package/lib/core/ws/WebSocketClientManager.js +73 -34
- package/lib/core/ws/WebSocketClientManager.js.map +1 -1
- package/lib/core/ws/WebSocketClientManager.mjs +73 -34
- package/lib/core/ws/WebSocketClientManager.mjs.map +1 -1
- package/lib/core/ws.js +4 -2
- package/lib/core/ws.js.map +1 -1
- package/lib/core/ws.mjs +4 -2
- package/lib/core/ws.mjs.map +1 -1
- package/lib/iife/index.js +278 -113
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/lib/native/index.js +5 -0
- package/lib/native/index.js.map +1 -1
- package/lib/native/index.mjs +6 -1
- package/lib/native/index.mjs.map +1 -1
- package/lib/node/index.js +5 -0
- package/lib/node/index.js.map +1 -1
- package/lib/node/index.mjs +6 -1
- package/lib/node/index.mjs.map +1 -1
- package/package.json +17 -5
- package/src/browser/setupWorker/start/createStartHandler.ts +6 -0
- package/src/browser/setupWorker/stop/createStop.ts +4 -0
- package/src/core/handlers/WebSocketHandler.ts +1 -2
- package/src/core/utils/internal/Disposable.ts +6 -3
- package/src/core/utils/internal/devUtils.test.ts +21 -0
- package/src/core/utils/internal/devUtils.ts +13 -0
- package/src/core/utils/matching/matchRequestUrl.test.ts +11 -0
- package/src/core/utils/matching/normalizePath.test.ts +7 -1
- package/src/core/utils/matching/normalizePath.ts +1 -0
- package/src/core/utils/request/onUnhandledRequest.test.ts +30 -4
- package/src/core/utils/request/onUnhandledRequest.ts +4 -4
- package/src/core/utils/url/cleanUrl.test.ts +8 -3
- package/src/core/utils/url/cleanUrl.ts +9 -1
- package/src/core/utils/url/getAbsoluteUrl.node.test.ts +3 -3
- package/src/core/utils/url/getAbsoluteUrl.test.ts +5 -5
- package/src/core/utils/url/isAbsoluteUrl.test.ts +7 -7
- package/src/core/ws/WebSocketClientManager.test.ts +43 -45
- package/src/core/ws/WebSocketClientManager.ts +107 -44
- package/src/core/ws.ts +4 -2
- package/src/node/SetupServerCommonApi.ts +7 -1
package/lib/mockServiceWorker.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Please do NOT serve this file on production.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const PACKAGE_VERSION = '2.3.0-ws.rc-
|
|
11
|
+
const PACKAGE_VERSION = '2.3.0-ws.rc-7'
|
|
12
12
|
const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
|
|
13
13
|
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
|
|
14
14
|
const activeClientIds = new Set()
|
package/lib/native/index.js
CHANGED
|
@@ -67,6 +67,11 @@ var SetupServerCommonApi = class extends import_SetupApi.SetupApi {
|
|
|
67
67
|
}
|
|
68
68
|
return;
|
|
69
69
|
});
|
|
70
|
+
this.interceptor.on("unhandledException", ({ error }) => {
|
|
71
|
+
if (error instanceof import_devUtils.InternalError) {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
70
75
|
this.interceptor.on(
|
|
71
76
|
"response",
|
|
72
77
|
({ response, isMockedResponse, request, requestId }) => {
|
package/lib/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/native/index.ts","../../src/node/SetupServerCommonApi.ts"],"sourcesContent":["import { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { SetupServerCommonApi } from '../node/SetupServerCommonApi'\n\n/**\n * Sets up a requests interception in React Native with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport function setupServer(\n ...handlers: Array<RequestHandler>\n): SetupServerCommonApi {\n // Provision request interception via patching the `XMLHttpRequest` class only\n // in React Native. There is no `http`/`https` modules in that environment.\n return new SetupServerCommonApi(\n [FetchInterceptor, XMLHttpRequestInterceptor],\n handlers,\n )\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AACjC,4BAA0C;;;ACI1C,wBAA0B;AAC1B,0BAKO;AAEP,sBAAyB;AACzB,2BAA8B;AAG9B,wBAA2B;AAC3B,
|
|
1
|
+
{"version":3,"sources":["../../src/native/index.ts","../../src/node/SetupServerCommonApi.ts"],"sourcesContent":["import { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { SetupServerCommonApi } from '../node/SetupServerCommonApi'\n\n/**\n * Sets up a requests interception in React Native with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport function setupServer(\n ...handlers: Array<RequestHandler>\n): SetupServerCommonApi {\n // Provision request interception via patching the `XMLHttpRequest` class only\n // in React Native. There is no `http`/`https` modules in that environment.\n return new SetupServerCommonApi(\n [FetchInterceptor, XMLHttpRequestInterceptor],\n handlers,\n )\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { InternalError, devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on('unhandledException', ({ error }) => {\n if (error instanceof InternalError) {\n throw error\n }\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AACjC,4BAA0C;;;ACI1C,wBAA0B;AAC1B,0BAKO;AAEP,sBAAyB;AACzB,2BAA8B;AAG9B,wBAA2B;AAC3B,sBAAwC;AAExC,kCAAqC;AACrC,kCAAqC;AAE9B,IAAM,yBAAsD;AAAA,EACjE,oBAAoB;AACtB;AAEO,IAAM,uBAAN,cACG,yBAEV;AAAA,EACqB;AAAA,EAIX;AAAA,EAER,YACE,cACA,UACA;AACA,UAAM,GAAG,QAAQ;AAEjB,SAAK,cAAc,IAAI,qCAAiB;AAAA,MACtC,MAAM;AAAA,MACN,cAAc,aAAa,IAAI,CAAC,gBAAgB,IAAI,YAAY,CAAC;AAAA,IACnE,CAAC;AAED,SAAK,kBAAkB,CAAC;AAExB,SAAK,KAAK;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAa;AACnB,SAAK,YAAY,GAAG,WAAW,OAAO,EAAE,SAAS,UAAU,MAAM;AAC/D,YAAM,WAAW,UAAM;AAAA,QACrB;AAAA,QACA;AAAA,QACA,KAAK,mBAAmB,gBAAgB;AAAA,QACxC,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAEA,UAAI,UAAU;AACZ,gBAAQ,YAAY,QAAQ;AAAA,MAC9B;AAEA;AAAA,IACF,CAAC;AAED,SAAK,YAAY,GAAG,sBAAsB,CAAC,EAAE,MAAM,MAAM;AACvD,UAAI,iBAAiB,+BAAe;AAClC,cAAM;AAAA,MACR;AAAA,IACF,CAAC;AAED,SAAK,YAAY;AAAA,MACf;AAAA,MACA,CAAC,EAAE,UAAU,kBAAkB,SAAS,UAAU,MAAM;AACtD,aAAK,QAAQ;AAAA,UACX,mBAAmB,oBAAoB;AAAA,UACvC;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,0DAAqB;AAAA,MACnB,aAAa,MAAM;AACjB,eAAO,KAAK,mBAAmB,gBAAgB;AAAA,MACjD;AAAA,MACA,oBAAoB,MAAM;AAAA,MAAC;AAAA,MAC3B,yBAAyB,MAAM;AAAA,MAAC;AAAA,IAClC,CAAC;AAAA,EACH;AAAA,EAEO,OAAO,UAAkC,CAAC,GAAS;AACxD,SAAK,sBAAkB;AAAA,MACrB;AAAA,MACA;AAAA,IACF;AAGA,SAAK,YAAY,MAAM;AACvB,qDAAqB,MAAM;AAE3B,SAAK,cAAc,KAAK,MAAM;AAC5B,WAAK,YAAY,QAAQ;AACzB,uDAAqB,QAAQ;AAAA,IAC/B,CAAC;AAKD;AAAA,MACE,CAAC,0CAAsB,UAAU,0CAAsB,OAAO,EAAE;AAAA,QAC9D,KAAK,YAAY;AAAA,MACnB;AAAA,MACA,yBAAS;AAAA,QACP;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEO,QAAc;AACnB,SAAK,QAAQ;AAAA,EACf;AACF;;;AD3HO,SAAS,eACX,UACmB;AAGtB,SAAO,IAAI;AAAA,IACT,CAAC,+BAAkB,+CAAyB;AAAA,IAC5C;AAAA,EACF;AACF;","names":[]}
|
package/lib/native/index.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { SetupApi } from '../core/SetupApi.mjs';
|
|
12
12
|
import { handleRequest } from '../core/utils/handleRequest.mjs';
|
|
13
13
|
import { mergeRight } from '../core/utils/internal/mergeRight.mjs';
|
|
14
|
-
import { devUtils } from '../core/utils/internal/devUtils.mjs';
|
|
14
|
+
import { InternalError, devUtils } from '../core/utils/internal/devUtils.mjs';
|
|
15
15
|
import { handleWebSocketEvent } from '../core/ws/handleWebSocketEvent.mjs';
|
|
16
16
|
import { webSocketInterceptor } from '../core/ws/webSocketInterceptor.mjs';
|
|
17
17
|
var DEFAULT_LISTEN_OPTIONS = {
|
|
@@ -46,6 +46,11 @@ var SetupServerCommonApi = class extends SetupApi {
|
|
|
46
46
|
}
|
|
47
47
|
return;
|
|
48
48
|
});
|
|
49
|
+
this.interceptor.on("unhandledException", ({ error }) => {
|
|
50
|
+
if (error instanceof InternalError) {
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
49
54
|
this.interceptor.on(
|
|
50
55
|
"response",
|
|
51
56
|
({ response, isMockedResponse, request, requestId }) => {
|
package/lib/native/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/native/index.ts","../../src/node/SetupServerCommonApi.ts"],"sourcesContent":["import { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { SetupServerCommonApi } from '../node/SetupServerCommonApi'\n\n/**\n * Sets up a requests interception in React Native with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport function setupServer(\n ...handlers: Array<RequestHandler>\n): SetupServerCommonApi {\n // Provision request interception via patching the `XMLHttpRequest` class only\n // in React Native. There is no `http`/`https` modules in that environment.\n return new SetupServerCommonApi(\n [FetchInterceptor, XMLHttpRequestInterceptor],\n handlers,\n )\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n"],"mappings":";AAAA,SAAS,wBAAwB;AACjC,SAAS,iCAAiC;;;ACI1C,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAEP,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAG9B,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;
|
|
1
|
+
{"version":3,"sources":["../../src/native/index.ts","../../src/node/SetupServerCommonApi.ts"],"sourcesContent":["import { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { SetupServerCommonApi } from '../node/SetupServerCommonApi'\n\n/**\n * Sets up a requests interception in React Native with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport function setupServer(\n ...handlers: Array<RequestHandler>\n): SetupServerCommonApi {\n // Provision request interception via patching the `XMLHttpRequest` class only\n // in React Native. There is no `http`/`https` modules in that environment.\n return new SetupServerCommonApi(\n [FetchInterceptor, XMLHttpRequestInterceptor],\n handlers,\n )\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { InternalError, devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on('unhandledException', ({ error }) => {\n if (error instanceof InternalError) {\n throw error\n }\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n"],"mappings":";AAAA,SAAS,wBAAwB;AACjC,SAAS,iCAAiC;;;ACI1C,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAEP,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAG9B,SAAS,kBAAkB;AAC3B,SAAS,eAAe,gBAAgB;AAExC,SAAS,4BAA4B;AACrC,SAAS,4BAA4B;AAE9B,IAAM,yBAAsD;AAAA,EACjE,oBAAoB;AACtB;AAEO,IAAM,uBAAN,cACG,SAEV;AAAA,EACqB;AAAA,EAIX;AAAA,EAER,YACE,cACA,UACA;AACA,UAAM,GAAG,QAAQ;AAEjB,SAAK,cAAc,IAAI,iBAAiB;AAAA,MACtC,MAAM;AAAA,MACN,cAAc,aAAa,IAAI,CAAC,gBAAgB,IAAI,YAAY,CAAC;AAAA,IACnE,CAAC;AAED,SAAK,kBAAkB,CAAC;AAExB,SAAK,KAAK;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAa;AACnB,SAAK,YAAY,GAAG,WAAW,OAAO,EAAE,SAAS,UAAU,MAAM;AAC/D,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,QACA;AAAA,QACA,KAAK,mBAAmB,gBAAgB;AAAA,QACxC,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAEA,UAAI,UAAU;AACZ,gBAAQ,YAAY,QAAQ;AAAA,MAC9B;AAEA;AAAA,IACF,CAAC;AAED,SAAK,YAAY,GAAG,sBAAsB,CAAC,EAAE,MAAM,MAAM;AACvD,UAAI,iBAAiB,eAAe;AAClC,cAAM;AAAA,MACR;AAAA,IACF,CAAC;AAED,SAAK,YAAY;AAAA,MACf;AAAA,MACA,CAAC,EAAE,UAAU,kBAAkB,SAAS,UAAU,MAAM;AACtD,aAAK,QAAQ;AAAA,UACX,mBAAmB,oBAAoB;AAAA,UACvC;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,yBAAqB;AAAA,MACnB,aAAa,MAAM;AACjB,eAAO,KAAK,mBAAmB,gBAAgB;AAAA,MACjD;AAAA,MACA,oBAAoB,MAAM;AAAA,MAAC;AAAA,MAC3B,yBAAyB,MAAM;AAAA,MAAC;AAAA,IAClC,CAAC;AAAA,EACH;AAAA,EAEO,OAAO,UAAkC,CAAC,GAAS;AACxD,SAAK,kBAAkB;AAAA,MACrB;AAAA,MACA;AAAA,IACF;AAGA,SAAK,YAAY,MAAM;AACvB,yBAAqB,MAAM;AAE3B,SAAK,cAAc,KAAK,MAAM;AAC5B,WAAK,YAAY,QAAQ;AACzB,2BAAqB,QAAQ;AAAA,IAC/B,CAAC;AAKD;AAAA,MACE,CAAC,sBAAsB,UAAU,sBAAsB,OAAO,EAAE;AAAA,QAC9D,KAAK,YAAY;AAAA,MACnB;AAAA,MACA,SAAS;AAAA,QACP;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEO,QAAc;AACnB,SAAK,QAAQ;AAAA,EACf;AACF;;;AD3HO,SAAS,eACX,UACmB;AAGtB,SAAO,IAAI;AAAA,IACT,CAAC,kBAAkB,yBAAyB;AAAA,IAC5C;AAAA,EACF;AACF;","names":[]}
|
package/lib/node/index.js
CHANGED
|
@@ -72,6 +72,11 @@ var SetupServerCommonApi = class extends import_SetupApi.SetupApi {
|
|
|
72
72
|
}
|
|
73
73
|
return;
|
|
74
74
|
});
|
|
75
|
+
this.interceptor.on("unhandledException", ({ error }) => {
|
|
76
|
+
if (error instanceof import_devUtils.InternalError) {
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
75
80
|
this.interceptor.on(
|
|
76
81
|
"response",
|
|
77
82
|
({ response, isMockedResponse, request, requestId }) => {
|
package/lib/node/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/node/index.ts","../../src/node/SetupServerApi.ts","../../src/node/SetupServerCommonApi.ts","../../src/node/setupServer.ts"],"sourcesContent":["export type { SetupServer } from './glossary'\nexport { SetupServerApi } from './SetupServerApi'\nexport { setupServer } from './setupServer'\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { HandlersController } from '~/core/SetupApi'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport type { SetupServer } from './glossary'\nimport { SetupServerCommonApi } from './SetupServerCommonApi'\n\nconst store = new AsyncLocalStorage<RequestHandlersContext>()\n\ntype RequestHandlersContext = {\n initialHandlers: Array<RequestHandler | WebSocketHandler>\n handlers: Array<RequestHandler | WebSocketHandler>\n}\n\n/**\n * A handlers controller that utilizes `AsyncLocalStorage` in Node.js\n * to prevent the request handlers list from being a shared state\n * across mutliple tests.\n */\nclass AsyncHandlersController implements HandlersController {\n private rootContext: RequestHandlersContext\n\n constructor(initialHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.rootContext = { initialHandlers, handlers: [] }\n }\n\n get context(): RequestHandlersContext {\n return store.getStore() || this.rootContext\n }\n\n public prepend(runtimeHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.context.handlers.unshift(...runtimeHandlers)\n }\n\n public reset(nextHandlers: Array<RequestHandler | WebSocketHandler>) {\n const context = this.context\n context.handlers = []\n context.initialHandlers =\n nextHandlers.length > 0 ? nextHandlers : context.initialHandlers\n }\n\n public currentHandlers(): Array<RequestHandler | WebSocketHandler> {\n const { initialHandlers, handlers } = this.context\n return handlers.concat(initialHandlers)\n }\n}\n\nexport class SetupServerApi\n extends SetupServerCommonApi\n implements SetupServer\n{\n constructor(handlers: Array<RequestHandler | WebSocketHandler>) {\n super(\n [ClientRequestInterceptor, XMLHttpRequestInterceptor, FetchInterceptor],\n handlers,\n )\n\n this.handlersController = new AsyncHandlersController(handlers)\n }\n\n public boundary<Args extends Array<any>, R>(\n callback: (...args: Args) => R,\n ): (...args: Args) => R {\n return (...args: Args): R => {\n return store.run<any, any>(\n {\n initialHandlers: this.handlersController.currentHandlers(),\n handlers: [],\n },\n callback,\n ...args,\n )\n }\n }\n\n public close(): void {\n super.close()\n store.disable()\n }\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n","import type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { SetupServerApi } from './SetupServerApi'\n\n/**\n * Sets up a requests interception in Node.js with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport const setupServer = (\n ...handlers: Array<RequestHandler | WebSocketHandler>\n): SetupServerApi => {\n return new SetupServerApi(handlers)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/node/index.ts","../../src/node/SetupServerApi.ts","../../src/node/SetupServerCommonApi.ts","../../src/node/setupServer.ts"],"sourcesContent":["export type { SetupServer } from './glossary'\nexport { SetupServerApi } from './SetupServerApi'\nexport { setupServer } from './setupServer'\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { HandlersController } from '~/core/SetupApi'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport type { SetupServer } from './glossary'\nimport { SetupServerCommonApi } from './SetupServerCommonApi'\n\nconst store = new AsyncLocalStorage<RequestHandlersContext>()\n\ntype RequestHandlersContext = {\n initialHandlers: Array<RequestHandler | WebSocketHandler>\n handlers: Array<RequestHandler | WebSocketHandler>\n}\n\n/**\n * A handlers controller that utilizes `AsyncLocalStorage` in Node.js\n * to prevent the request handlers list from being a shared state\n * across mutliple tests.\n */\nclass AsyncHandlersController implements HandlersController {\n private rootContext: RequestHandlersContext\n\n constructor(initialHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.rootContext = { initialHandlers, handlers: [] }\n }\n\n get context(): RequestHandlersContext {\n return store.getStore() || this.rootContext\n }\n\n public prepend(runtimeHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.context.handlers.unshift(...runtimeHandlers)\n }\n\n public reset(nextHandlers: Array<RequestHandler | WebSocketHandler>) {\n const context = this.context\n context.handlers = []\n context.initialHandlers =\n nextHandlers.length > 0 ? nextHandlers : context.initialHandlers\n }\n\n public currentHandlers(): Array<RequestHandler | WebSocketHandler> {\n const { initialHandlers, handlers } = this.context\n return handlers.concat(initialHandlers)\n }\n}\n\nexport class SetupServerApi\n extends SetupServerCommonApi\n implements SetupServer\n{\n constructor(handlers: Array<RequestHandler | WebSocketHandler>) {\n super(\n [ClientRequestInterceptor, XMLHttpRequestInterceptor, FetchInterceptor],\n handlers,\n )\n\n this.handlersController = new AsyncHandlersController(handlers)\n }\n\n public boundary<Args extends Array<any>, R>(\n callback: (...args: Args) => R,\n ): (...args: Args) => R {\n return (...args: Args): R => {\n return store.run<any, any>(\n {\n initialHandlers: this.handlersController.currentHandlers(),\n handlers: [],\n },\n callback,\n ...args,\n )\n }\n }\n\n public close(): void {\n super.close()\n store.disable()\n }\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { InternalError, devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on('unhandledException', ({ error }) => {\n if (error instanceof InternalError) {\n throw error\n }\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n","import type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { SetupServerApi } from './SetupServerApi'\n\n/**\n * Sets up a requests interception in Node.js with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport const setupServer = (\n ...handlers: Array<RequestHandler | WebSocketHandler>\n): SetupServerApi => {\n return new SetupServerApi(handlers)\n}\n"],"mappings":"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","names":[]}
|
package/lib/node/index.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import { SetupApi } from '../core/SetupApi.mjs';
|
|
14
14
|
import { handleRequest } from '../core/utils/handleRequest.mjs';
|
|
15
15
|
import { mergeRight } from '../core/utils/internal/mergeRight.mjs';
|
|
16
|
-
import { devUtils } from '../core/utils/internal/devUtils.mjs';
|
|
16
|
+
import { InternalError, devUtils } from '../core/utils/internal/devUtils.mjs';
|
|
17
17
|
import { handleWebSocketEvent } from '../core/ws/handleWebSocketEvent.mjs';
|
|
18
18
|
import { webSocketInterceptor } from '../core/ws/webSocketInterceptor.mjs';
|
|
19
19
|
var DEFAULT_LISTEN_OPTIONS = {
|
|
@@ -48,6 +48,11 @@ var SetupServerCommonApi = class extends SetupApi {
|
|
|
48
48
|
}
|
|
49
49
|
return;
|
|
50
50
|
});
|
|
51
|
+
this.interceptor.on("unhandledException", ({ error }) => {
|
|
52
|
+
if (error instanceof InternalError) {
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
51
56
|
this.interceptor.on(
|
|
52
57
|
"response",
|
|
53
58
|
({ response, isMockedResponse, request, requestId }) => {
|
package/lib/node/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/node/SetupServerApi.ts","../../src/node/SetupServerCommonApi.ts","../../src/node/setupServer.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { HandlersController } from '~/core/SetupApi'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport type { SetupServer } from './glossary'\nimport { SetupServerCommonApi } from './SetupServerCommonApi'\n\nconst store = new AsyncLocalStorage<RequestHandlersContext>()\n\ntype RequestHandlersContext = {\n initialHandlers: Array<RequestHandler | WebSocketHandler>\n handlers: Array<RequestHandler | WebSocketHandler>\n}\n\n/**\n * A handlers controller that utilizes `AsyncLocalStorage` in Node.js\n * to prevent the request handlers list from being a shared state\n * across mutliple tests.\n */\nclass AsyncHandlersController implements HandlersController {\n private rootContext: RequestHandlersContext\n\n constructor(initialHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.rootContext = { initialHandlers, handlers: [] }\n }\n\n get context(): RequestHandlersContext {\n return store.getStore() || this.rootContext\n }\n\n public prepend(runtimeHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.context.handlers.unshift(...runtimeHandlers)\n }\n\n public reset(nextHandlers: Array<RequestHandler | WebSocketHandler>) {\n const context = this.context\n context.handlers = []\n context.initialHandlers =\n nextHandlers.length > 0 ? nextHandlers : context.initialHandlers\n }\n\n public currentHandlers(): Array<RequestHandler | WebSocketHandler> {\n const { initialHandlers, handlers } = this.context\n return handlers.concat(initialHandlers)\n }\n}\n\nexport class SetupServerApi\n extends SetupServerCommonApi\n implements SetupServer\n{\n constructor(handlers: Array<RequestHandler | WebSocketHandler>) {\n super(\n [ClientRequestInterceptor, XMLHttpRequestInterceptor, FetchInterceptor],\n handlers,\n )\n\n this.handlersController = new AsyncHandlersController(handlers)\n }\n\n public boundary<Args extends Array<any>, R>(\n callback: (...args: Args) => R,\n ): (...args: Args) => R {\n return (...args: Args): R => {\n return store.run<any, any>(\n {\n initialHandlers: this.handlersController.currentHandlers(),\n handlers: [],\n },\n callback,\n ...args,\n )\n }\n }\n\n public close(): void {\n super.close()\n store.disable()\n }\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n","import type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { SetupServerApi } from './SetupServerApi'\n\n/**\n * Sets up a requests interception in Node.js with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport const setupServer = (\n ...handlers: Array<RequestHandler | WebSocketHandler>\n): SetupServerApi => {\n return new SetupServerApi(handlers)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/node/SetupServerApi.ts","../../src/node/SetupServerCommonApi.ts","../../src/node/setupServer.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { HandlersController } from '~/core/SetupApi'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport type { SetupServer } from './glossary'\nimport { SetupServerCommonApi } from './SetupServerCommonApi'\n\nconst store = new AsyncLocalStorage<RequestHandlersContext>()\n\ntype RequestHandlersContext = {\n initialHandlers: Array<RequestHandler | WebSocketHandler>\n handlers: Array<RequestHandler | WebSocketHandler>\n}\n\n/**\n * A handlers controller that utilizes `AsyncLocalStorage` in Node.js\n * to prevent the request handlers list from being a shared state\n * across mutliple tests.\n */\nclass AsyncHandlersController implements HandlersController {\n private rootContext: RequestHandlersContext\n\n constructor(initialHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.rootContext = { initialHandlers, handlers: [] }\n }\n\n get context(): RequestHandlersContext {\n return store.getStore() || this.rootContext\n }\n\n public prepend(runtimeHandlers: Array<RequestHandler | WebSocketHandler>) {\n this.context.handlers.unshift(...runtimeHandlers)\n }\n\n public reset(nextHandlers: Array<RequestHandler | WebSocketHandler>) {\n const context = this.context\n context.handlers = []\n context.initialHandlers =\n nextHandlers.length > 0 ? nextHandlers : context.initialHandlers\n }\n\n public currentHandlers(): Array<RequestHandler | WebSocketHandler> {\n const { initialHandlers, handlers } = this.context\n return handlers.concat(initialHandlers)\n }\n}\n\nexport class SetupServerApi\n extends SetupServerCommonApi\n implements SetupServer\n{\n constructor(handlers: Array<RequestHandler | WebSocketHandler>) {\n super(\n [ClientRequestInterceptor, XMLHttpRequestInterceptor, FetchInterceptor],\n handlers,\n )\n\n this.handlersController = new AsyncHandlersController(handlers)\n }\n\n public boundary<Args extends Array<any>, R>(\n callback: (...args: Args) => R,\n ): (...args: Args) => R {\n return (...args: Args): R => {\n return store.run<any, any>(\n {\n initialHandlers: this.handlersController.currentHandlers(),\n handlers: [],\n },\n callback,\n ...args,\n )\n }\n }\n\n public close(): void {\n super.close()\n store.disable()\n }\n}\n","/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n BatchInterceptor,\n InterceptorReadyState,\n type HttpRequestEventMap,\n type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { InternalError, devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\n\nexport const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n extends SetupApi<LifeCycleEventsMap>\n implements SetupServerCommon\n{\n protected readonly interceptor: BatchInterceptor<\n Array<Interceptor<HttpRequestEventMap>>,\n HttpRequestEventMap\n >\n private resolvedOptions: RequiredDeep<SharedOptions>\n\n constructor(\n interceptors: Array<{ new (): Interceptor<HttpRequestEventMap> }>,\n handlers: Array<RequestHandler | WebSocketHandler>,\n ) {\n super(...handlers)\n\n this.interceptor = new BatchInterceptor({\n name: 'setup-server',\n interceptors: interceptors.map((Interceptor) => new Interceptor()),\n })\n\n this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n\n this.init()\n }\n\n /**\n * Subscribe to all requests that are using the interceptor object\n */\n private init(): void {\n this.interceptor.on('request', async ({ request, requestId }) => {\n const response = await handleRequest(\n request,\n requestId,\n this.handlersController.currentHandlers(),\n this.resolvedOptions,\n this.emitter,\n )\n\n if (response) {\n request.respondWith(response)\n }\n\n return\n })\n\n this.interceptor.on('unhandledException', ({ error }) => {\n if (error instanceof InternalError) {\n throw error\n }\n })\n\n this.interceptor.on(\n 'response',\n ({ response, isMockedResponse, request, requestId }) => {\n this.emitter.emit(\n isMockedResponse ? 'response:mocked' : 'response:bypass',\n {\n response,\n request,\n requestId,\n },\n )\n },\n )\n\n handleWebSocketEvent({\n getHandlers: () => {\n return this.handlersController.currentHandlers()\n },\n onMockedConnection: () => {},\n onPassthroughConnection: () => {},\n })\n }\n\n public listen(options: Partial<SharedOptions> = {}): void {\n this.resolvedOptions = mergeRight(\n DEFAULT_LISTEN_OPTIONS,\n options,\n ) as RequiredDeep<SharedOptions>\n\n // Apply the interceptor when starting the server.\n this.interceptor.apply()\n webSocketInterceptor.apply()\n\n this.subscriptions.push(() => {\n this.interceptor.dispose()\n webSocketInterceptor.dispose()\n })\n\n // Assert that the interceptor has been applied successfully.\n // Also guards us from forgetting to call \"interceptor.apply()\"\n // as a part of the \"listen\" method.\n invariant(\n [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n this.interceptor.readyState,\n ),\n devUtils.formatMessage(\n 'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n ),\n 'https://github.com/mswjs/msw/issues/new/choose',\n )\n }\n\n public close(): void {\n this.dispose()\n }\n}\n","import type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { SetupServerApi } from './SetupServerApi'\n\n/**\n * Sets up a requests interception in Node.js with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport const setupServer = (\n ...handlers: Array<RequestHandler | WebSocketHandler>\n): SetupServerApi => {\n return new SetupServerApi(handlers)\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msw",
|
|
3
|
-
"version": "2.3.0-ws.rc-
|
|
3
|
+
"version": "2.3.0-ws.rc-7",
|
|
4
4
|
"description": "Seamless REST/GraphQL API mocking library for browser and Node.js.",
|
|
5
5
|
"main": "./lib/core/index.js",
|
|
6
6
|
"module": "./lib/core/index.mjs",
|
|
@@ -14,22 +14,34 @@
|
|
|
14
14
|
"default": "./lib/core/index.js"
|
|
15
15
|
},
|
|
16
16
|
"./browser": {
|
|
17
|
-
"node": null,
|
|
18
17
|
"types": "./lib/browser/index.d.ts",
|
|
18
|
+
"browser": {
|
|
19
|
+
"require": "./lib/browser/index.js",
|
|
20
|
+
"import": "./lib/browser/index.mjs"
|
|
21
|
+
},
|
|
22
|
+
"node": null,
|
|
19
23
|
"require": "./lib/browser/index.js",
|
|
20
24
|
"import": "./lib/browser/index.mjs",
|
|
21
25
|
"default": "./lib/browser/index.js"
|
|
22
26
|
},
|
|
23
27
|
"./node": {
|
|
24
|
-
"browser": null,
|
|
25
28
|
"types": "./lib/node/index.d.ts",
|
|
29
|
+
"node": {
|
|
30
|
+
"require": "./lib/node/index.js",
|
|
31
|
+
"import": "./lib/node/index.mjs"
|
|
32
|
+
},
|
|
33
|
+
"browser": null,
|
|
26
34
|
"require": "./lib/node/index.js",
|
|
27
35
|
"import": "./lib/node/index.mjs",
|
|
28
36
|
"default": "./lib/node/index.mjs"
|
|
29
37
|
},
|
|
30
38
|
"./native": {
|
|
31
|
-
"browser": null,
|
|
32
39
|
"types": "./lib/native/index.d.ts",
|
|
40
|
+
"react-native": {
|
|
41
|
+
"require": "./lib/native/index.js",
|
|
42
|
+
"import": "./lib/native/index.mjs"
|
|
43
|
+
},
|
|
44
|
+
"browser": null,
|
|
33
45
|
"require": "./lib/native/index.js",
|
|
34
46
|
"import": "./lib/native/index.mjs",
|
|
35
47
|
"default": "./lib/native/index.js"
|
|
@@ -125,7 +137,7 @@
|
|
|
125
137
|
"@bundled-es-modules/statuses": "^1.0.1",
|
|
126
138
|
"@inquirer/confirm": "^3.0.0",
|
|
127
139
|
"@mswjs/cookies": "^1.1.0",
|
|
128
|
-
"@mswjs/interceptors": "^0.
|
|
140
|
+
"@mswjs/interceptors": "^0.30.0",
|
|
129
141
|
"@open-draft/until": "^2.1.0",
|
|
130
142
|
"@types/cookie": "^0.6.0",
|
|
131
143
|
"@types/statuses": "^2.0.4",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { devUtils } from '~/core/utils/internal/devUtils'
|
|
2
|
+
import { MSW_WEBSOCKET_CLIENTS_KEY } from '~/core/ws/WebSocketClientManager'
|
|
2
3
|
import { getWorkerInstance } from './utils/getWorkerInstance'
|
|
3
4
|
import { enableMocking } from './utils/enableMocking'
|
|
4
5
|
import { SetupWorkerInternalContext, StartHandler } from '../glossary'
|
|
@@ -71,6 +72,11 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
|
|
|
71
72
|
// Make sure we're always clearing the interval - there are reports that not doing this can
|
|
72
73
|
// cause memory leaks in headless browser environments.
|
|
73
74
|
window.clearInterval(context.keepAliveInterval)
|
|
75
|
+
|
|
76
|
+
// Purge persisted clients on page reload.
|
|
77
|
+
// WebSocket clients will get new IDs on reload so persisting them
|
|
78
|
+
// makes little sense.
|
|
79
|
+
localStorage.removeItem(MSW_WEBSOCKET_CLIENTS_KEY)
|
|
74
80
|
})
|
|
75
81
|
|
|
76
82
|
// Check if the active Service Worker has been generated
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { devUtils } from '~/core/utils/internal/devUtils'
|
|
2
|
+
import { MSW_WEBSOCKET_CLIENTS_KEY } from '~/core/ws/WebSocketClientManager'
|
|
2
3
|
import { SetupWorkerInternalContext, StopHandler } from '../glossary'
|
|
3
4
|
import { printStopMessage } from './utils/printStopMessage'
|
|
4
5
|
|
|
@@ -24,6 +25,9 @@ export const createStop = (
|
|
|
24
25
|
context.isMockingEnabled = false
|
|
25
26
|
window.clearInterval(context.keepAliveInterval)
|
|
26
27
|
|
|
28
|
+
// Clear the WebSocket clients from the shared storage.
|
|
29
|
+
localStorage.removeItem(MSW_WEBSOCKET_CLIENTS_KEY)
|
|
30
|
+
|
|
27
31
|
printStopMessage({ quiet: context.startOptions?.quiet })
|
|
28
32
|
}
|
|
29
33
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
export type DisposableSubscription = () =>
|
|
1
|
+
export type DisposableSubscription = () => void
|
|
2
2
|
|
|
3
3
|
export class Disposable {
|
|
4
4
|
protected subscriptions: Array<DisposableSubscription> = []
|
|
5
5
|
|
|
6
|
-
public
|
|
7
|
-
|
|
6
|
+
public dispose() {
|
|
7
|
+
let subscription: DisposableSubscription | undefined
|
|
8
|
+
while ((subscription = this.subscriptions.shift())) {
|
|
9
|
+
subscription()
|
|
10
|
+
}
|
|
8
11
|
}
|
|
9
12
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { InternalError } from './devUtils'
|
|
2
|
+
|
|
3
|
+
describe(InternalError, () => {
|
|
4
|
+
it('creates an InternalError instance', () => {
|
|
5
|
+
const error = new InternalError('Message')
|
|
6
|
+
|
|
7
|
+
expect(error.name).toBe('InternalError')
|
|
8
|
+
expect(error.message).toBe('Message')
|
|
9
|
+
expect(error.toString()).toBe('InternalError: Message')
|
|
10
|
+
expect(error.stack).toMatch(/\w+/)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('passes the identity check', () => {
|
|
14
|
+
const error = new InternalError('Message')
|
|
15
|
+
expect(error instanceof InternalError).toBe(true)
|
|
16
|
+
expect(error instanceof Error).toBe(true)
|
|
17
|
+
|
|
18
|
+
const extraneousError = new Error('Message')
|
|
19
|
+
expect(extraneousError).not.toBeInstanceOf(InternalError)
|
|
20
|
+
})
|
|
21
|
+
})
|
|
@@ -29,3 +29,16 @@ export const devUtils = {
|
|
|
29
29
|
warn,
|
|
30
30
|
error,
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Internal error instance.
|
|
35
|
+
* Used to differentiate the library errors that must be forwarded
|
|
36
|
+
* to the user from the unhandled exceptions. Use this if you don't
|
|
37
|
+
* wish for the error to be coerced to a 500 fallback response.
|
|
38
|
+
*/
|
|
39
|
+
export class InternalError extends Error {
|
|
40
|
+
constructor(message: string) {
|
|
41
|
+
super(message)
|
|
42
|
+
this.name = 'InternalError'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -62,6 +62,17 @@ describe('matchRequestUrl', () => {
|
|
|
62
62
|
expect(match).toHaveProperty('params', {})
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
+
test('returns true when matching optional path parameters', () => {
|
|
66
|
+
const match = matchRequestUrl(
|
|
67
|
+
new URL('https://test.mswjs.io/user'),
|
|
68
|
+
'https://test.mswjs.io/user/:userId?',
|
|
69
|
+
)
|
|
70
|
+
expect(match).toHaveProperty('matches', true)
|
|
71
|
+
expect(match).toHaveProperty('params', {
|
|
72
|
+
userId: undefined,
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
65
76
|
test('returns true for matching WebSocket URL', () => {
|
|
66
77
|
expect(
|
|
67
78
|
matchRequestUrl(new URL('ws://test.mswjs.io'), 'ws://test.mswjs.io'),
|
|
@@ -43,8 +43,14 @@ test('returns a path pattern string as-is', () => {
|
|
|
43
43
|
expect(normalizePath('*/resource/*')).toEqual('*/resource/*')
|
|
44
44
|
})
|
|
45
45
|
|
|
46
|
-
test('
|
|
46
|
+
test('removes query parameters and hashes from a path pattern string', () => {
|
|
47
47
|
expect(normalizePath(':api/user?query=123#some')).toEqual(
|
|
48
48
|
'http://localhost/:api/user',
|
|
49
49
|
)
|
|
50
50
|
})
|
|
51
|
+
|
|
52
|
+
test('preserves optional path parameters', () => {
|
|
53
|
+
expect(normalizePath('/user/:userId?')).toEqual(
|
|
54
|
+
'http://localhost/user/:userId?',
|
|
55
|
+
)
|
|
56
|
+
})
|
|
@@ -8,6 +8,7 @@ import { getAbsoluteUrl } from '../url/getAbsoluteUrl'
|
|
|
8
8
|
* - Removes query parameters and hashes.
|
|
9
9
|
* - Rebases relative URLs against the "baseUrl" or the current location.
|
|
10
10
|
* - Preserves relative URLs in Node.js, unless specified otherwise.
|
|
11
|
+
* - Preserves optional path parameters.
|
|
11
12
|
*/
|
|
12
13
|
export function normalizePath(path: Path, baseUrl?: string): Path {
|
|
13
14
|
// RegExp paths do not need normalization.
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
} from './onUnhandledRequest'
|
|
8
8
|
|
|
9
9
|
const fixtures = {
|
|
10
|
-
warningWithoutSuggestions: `\
|
|
10
|
+
warningWithoutSuggestions: (url = `/api`) => `\
|
|
11
11
|
[MSW] Warning: intercepted a request without a matching request handler:
|
|
12
12
|
|
|
13
|
-
• GET
|
|
13
|
+
• GET ${url}
|
|
14
14
|
|
|
15
15
|
If you still wish to intercept this unhandled request, please create a request handler for it.
|
|
16
16
|
Read more: https://mswjs.io/docs/getting-started/mocks`,
|
|
@@ -46,7 +46,9 @@ test('supports the "bypass" request strategy', async () => {
|
|
|
46
46
|
test('supports the "warn" request strategy', async () => {
|
|
47
47
|
await onUnhandledRequest(new Request(new URL('http://localhost/api')), 'warn')
|
|
48
48
|
|
|
49
|
-
expect(console.warn).toHaveBeenCalledWith(
|
|
49
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
50
|
+
fixtures.warningWithoutSuggestions(),
|
|
51
|
+
)
|
|
50
52
|
})
|
|
51
53
|
|
|
52
54
|
test('supports the "error" request strategy', async () => {
|
|
@@ -103,7 +105,9 @@ test('supports calling default strategies from the custom callback function', as
|
|
|
103
105
|
test('does not print any suggestions given no handlers to suggest', async () => {
|
|
104
106
|
await onUnhandledRequest(new Request(new URL('http://localhost/api')), 'warn')
|
|
105
107
|
|
|
106
|
-
expect(console.warn).toHaveBeenCalledWith(
|
|
108
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
109
|
+
fixtures.warningWithoutSuggestions(),
|
|
110
|
+
)
|
|
107
111
|
})
|
|
108
112
|
|
|
109
113
|
test('throws an exception given unknown request strategy', async () => {
|
|
@@ -117,3 +121,25 @@ test('throws an exception given unknown request strategy', async () => {
|
|
|
117
121
|
'[MSW] Failed to react to an unhandled request: unknown strategy "invalid-strategy". Please provide one of the supported strategies ("bypass", "warn", "error") or a custom callback function as the value of the "onUnhandledRequest" option.',
|
|
118
122
|
)
|
|
119
123
|
})
|
|
124
|
+
|
|
125
|
+
test('prints with a relative URL and search params', async () => {
|
|
126
|
+
await onUnhandledRequest(
|
|
127
|
+
new Request(new URL('http://localhost/api?foo=boo')),
|
|
128
|
+
'warn',
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
132
|
+
fixtures.warningWithoutSuggestions(`/api?foo=boo`),
|
|
133
|
+
)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('prints with an absolute URL and search params', async () => {
|
|
137
|
+
await onUnhandledRequest(
|
|
138
|
+
new Request(new URL('https://mswjs.io/api?foo=boo')),
|
|
139
|
+
'warn',
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
143
|
+
fixtures.warningWithoutSuggestions(`https://mswjs.io/api?foo=boo`),
|
|
144
|
+
)
|
|
145
|
+
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toPublicUrl } from './toPublicUrl'
|
|
2
|
-
import { devUtils } from '../internal/devUtils'
|
|
2
|
+
import { InternalError, devUtils } from '../internal/devUtils'
|
|
3
3
|
|
|
4
4
|
export interface UnhandledRequestPrint {
|
|
5
5
|
warning(): void
|
|
@@ -22,7 +22,7 @@ export async function onUnhandledRequest(
|
|
|
22
22
|
strategy: UnhandledRequestStrategy = 'warn',
|
|
23
23
|
): Promise<void> {
|
|
24
24
|
const url = new URL(request.url)
|
|
25
|
-
const publicUrl = toPublicUrl(url)
|
|
25
|
+
const publicUrl = toPublicUrl(url) + url.search
|
|
26
26
|
|
|
27
27
|
const unhandledRequestMessage = `intercepted a request without a matching request handler:\n\n \u2022 ${request.method} ${publicUrl}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/getting-started/mocks`
|
|
28
28
|
|
|
@@ -33,7 +33,7 @@ export async function onUnhandledRequest(
|
|
|
33
33
|
devUtils.error('Error: %s', unhandledRequestMessage)
|
|
34
34
|
|
|
35
35
|
// Throw an exception to halt request processing and not perform the original request.
|
|
36
|
-
throw new
|
|
36
|
+
throw new InternalError(
|
|
37
37
|
devUtils.formatMessage(
|
|
38
38
|
'Cannot bypass a request when using the "error" strategy for the "onUnhandledRequest" option.',
|
|
39
39
|
),
|
|
@@ -49,7 +49,7 @@ export async function onUnhandledRequest(
|
|
|
49
49
|
break
|
|
50
50
|
|
|
51
51
|
default:
|
|
52
|
-
throw new
|
|
52
|
+
throw new InternalError(
|
|
53
53
|
devUtils.formatMessage(
|
|
54
54
|
'Failed to react to an unhandled request: unknown strategy "%s". Please provide one of the supported strategies ("bypass", "warn", "error") or a custom callback function as the value of the "onUnhandledRequest" option.',
|
|
55
55
|
strategy,
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { cleanUrl } from './cleanUrl'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
it('removes query parameters from a URL string', () => {
|
|
4
4
|
expect(cleanUrl('/user?id=123')).toEqual('/user')
|
|
5
5
|
expect(cleanUrl('/user?id=123&id=456')).toEqual('/user')
|
|
6
6
|
expect(cleanUrl('/user?id=123&role=admin')).toEqual('/user')
|
|
7
7
|
})
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
it('removes hashes from a URL string', () => {
|
|
10
10
|
expect(cleanUrl('/user#hash')).toEqual('/user')
|
|
11
11
|
expect(cleanUrl('/user#hash-with-dashes')).toEqual('/user')
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
it('removes both query parameters and hashes from a URL string', () => {
|
|
15
15
|
expect(cleanUrl('/user?id=123#some')).toEqual('/user')
|
|
16
16
|
expect(cleanUrl('/user?id=123&role=admin#some')).toEqual('/user')
|
|
17
17
|
})
|
|
18
|
+
|
|
19
|
+
it('preserves optional path parameters', () => {
|
|
20
|
+
expect(cleanUrl('/user/:id?')).toEqual('/user/:id?')
|
|
21
|
+
expect(cleanUrl('/user/:id?/:messageId?')).toEqual('/user/:id?/:messageId?')
|
|
22
|
+
})
|
|
@@ -5,8 +5,16 @@ export function getSearchParams(path: string) {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Removes
|
|
8
|
+
* Removes search parameters and the fragment
|
|
9
|
+
* from a given URL string.
|
|
9
10
|
*/
|
|
10
11
|
export function cleanUrl(path: string): string {
|
|
12
|
+
// If the path ends with an optional path parameter,
|
|
13
|
+
// return it as-is.
|
|
14
|
+
if (path.endsWith('?')) {
|
|
15
|
+
return path
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Otherwise, remove the search and fragment from it.
|
|
11
19
|
return path.replace(REDUNDANT_CHARACTERS_EXP, '')
|
|
12
20
|
}
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { getAbsoluteUrl } from './getAbsoluteUrl'
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
it('returns a given relative URL as-is', () => {
|
|
7
7
|
expect(getAbsoluteUrl('/reviews')).toBe('/reviews')
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
it('rebases a relative URL against a custom base URL', () => {
|
|
11
11
|
expect(getAbsoluteUrl('/user', 'https://api.github.com')).toEqual(
|
|
12
12
|
'https://api.github.com/user',
|
|
13
13
|
)
|
|
14
14
|
})
|
|
15
|
-
|
|
15
|
+
it('returns a given absolute URL as-is', () => {
|
|
16
16
|
expect(getAbsoluteUrl('https://api.mswjs.io/users')).toBe(
|
|
17
17
|
'https://api.mswjs.io/users',
|
|
18
18
|
)
|