msw 0.20.5 → 0.21.3

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -1
  3. package/lib/esm/fetch-deps.js +26 -23
  4. package/lib/esm/graphql.js +92 -79
  5. package/lib/esm/index.js +90 -44
  6. package/lib/esm/{matchRequest-deps.js → matchRequestUrl-deps.js} +29 -17
  7. package/lib/esm/mockServiceWorker.js +8 -1
  8. package/lib/esm/rest-deps.js +27 -18
  9. package/lib/esm/rest.js +1 -1
  10. package/lib/esm/xml-deps.js +3 -3
  11. package/lib/types/LiveStorage.d.ts +17 -0
  12. package/lib/types/context/body.d.ts +2 -2
  13. package/lib/types/context/errors.d.ts +3 -1
  14. package/lib/types/context/fetch.d.ts +2 -2
  15. package/lib/types/context/json.d.ts +5 -3
  16. package/lib/types/context/text.d.ts +2 -2
  17. package/lib/types/context/xml.d.ts +2 -2
  18. package/lib/types/graphql.d.ts +8 -10
  19. package/lib/types/index.d.ts +3 -3
  20. package/lib/types/native/index.d.ts +7 -1
  21. package/lib/types/node/createSetupServer.d.ts +29 -0
  22. package/lib/types/node/setupServer.d.ts +4 -24
  23. package/lib/types/response.d.ts +10 -7
  24. package/lib/types/rest.d.ts +158 -16
  25. package/lib/types/setupWorker/glossary.d.ts +14 -4
  26. package/lib/types/setupWorker/start/utils/getWorkerByRegistration.d.ts +2 -1
  27. package/lib/types/setupWorker/start/utils/getWorkerInstance.d.ts +2 -2
  28. package/lib/types/sharedOptions.d.ts +1 -1
  29. package/lib/types/utils/getResponse.d.ts +2 -2
  30. package/lib/types/utils/handlers/requestHandler.d.ts +74 -0
  31. package/lib/types/utils/{requestHandlerUtils.d.ts → handlers/requestHandlerUtils.d.ts} +2 -2
  32. package/lib/types/utils/{isNodeProcess.d.ts → internal/isNodeProcess.d.ts} +1 -0
  33. package/lib/types/utils/{isStringEqual.d.ts → internal/isStringEqual.d.ts} +0 -0
  34. package/lib/types/utils/{jsonParse.d.ts → internal/jsonParse.d.ts} +0 -0
  35. package/lib/types/utils/internal/mergeRight.d.ts +5 -0
  36. package/lib/types/utils/{logger → logging}/getStatusCodeColor.d.ts +0 -0
  37. package/lib/types/utils/{logger → logging}/getTimestamp.d.ts +0 -0
  38. package/lib/types/utils/{logger → logging}/prepareRequest.d.ts +3 -3
  39. package/lib/types/utils/{logger → logging}/prepareResponse.d.ts +2 -2
  40. package/lib/types/utils/matching/{matchRequest.d.ts → matchRequestUrl.d.ts} +0 -0
  41. package/lib/types/utils/request/getPublicUrlFromRequest.d.ts +6 -0
  42. package/lib/types/utils/request/getRequestCookies.d.ts +1 -1
  43. package/lib/types/{onUnhandledRequest.d.ts → utils/request/onUnhandledRequest.d.ts} +1 -1
  44. package/lib/types/utils/request/parseBody.d.ts +5 -0
  45. package/lib/types/utils/url/getAbsoluteUrl.d.ts +6 -0
  46. package/lib/types/utils/{getAbsoluteWorkerUrl.d.ts → url/getAbsoluteWorkerUrl.d.ts} +0 -0
  47. package/lib/types/utils/url/getUrlByMask.d.ts +5 -0
  48. package/lib/umd/index.js +696 -613
  49. package/lib/umd/mockServiceWorker.js +8 -1
  50. package/native/index.js +1508 -133
  51. package/node/context/delay.d.ts +11 -0
  52. package/node/context/fetch.d.ts +8 -0
  53. package/node/context/set.d.ts +2 -0
  54. package/node/context/status.d.ts +2 -0
  55. package/node/index.js +1507 -133
  56. package/node/node/createSetupServer.d.ts +29 -0
  57. package/node/node/index.d.ts +5 -0
  58. package/node/node/setupServer.d.ts +7 -0
  59. package/node/response.d.ts +25 -0
  60. package/node/utils/NetworkError.d.ts +3 -0
  61. package/node/utils/getResponse.d.ts +14 -0
  62. package/{lib/types → node/utils}/handlers/requestHandler.d.ts +13 -12
  63. package/node/utils/handlers/requestHandlerUtils.d.ts +4 -0
  64. package/node/utils/internal/compose.d.ts +5 -0
  65. package/node/utils/internal/isNodeProcess.d.ts +5 -0
  66. package/node/utils/internal/jsonParse.d.ts +5 -0
  67. package/node/utils/request/getPublicUrlFromRequest.d.ts +6 -0
  68. package/node/utils/request/onUnhandledRequest.d.ts +5 -0
  69. package/node/utils/request/parseBody.d.ts +5 -0
  70. package/package.json +34 -29
  71. package/lib/types/utils/getJsonBody.d.ts +0 -5
  72. package/lib/types/utils/request/parseRequestBody.d.ts +0 -2
  73. package/lib/types/utils/resolveMask.d.ts +0 -6
  74. package/lib/types/utils/resolveRelativeUrl.d.ts +0 -6
package/lib/umd/index.js CHANGED
@@ -88,11 +88,11 @@
88
88
 
89
89
  function createCommonjsModule(fn, basedir, module) {
90
90
  return module = {
91
- path: basedir,
92
- exports: {},
93
- require: function (path, base) {
94
- return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
95
- }
91
+ path: basedir,
92
+ exports: {},
93
+ require: function (path, base) {
94
+ return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
95
+ }
96
96
  }, fn(module, module.exports), module.exports;
97
97
  }
98
98
 
@@ -574,7 +574,7 @@
574
574
  /**
575
575
  * Sets the body of the response without any `Content-Type` header.
576
576
  * @example
577
- * res(body('foo'))
577
+ * res(body('message'))
578
578
  */
579
579
  const body = (value) => {
580
580
  return (res) => {
@@ -596,16 +596,16 @@
596
596
 
597
597
  /**
598
598
  * Returns a boolean indicating if the current process is running in NodeJS environment.
599
+ * @see https://github.com/mswjs/msw/pull/255
599
600
  */
600
- // Please see https://github.com/mswjs/msw/pull/255
601
601
  function isNodeProcess() {
602
+ // Check browser environment.
602
603
  if (typeof global !== 'object') {
603
- // check browser environment
604
604
  return false;
605
605
  }
606
+ // Check nodejs or React Native environment.
606
607
  if (Object.prototype.toString.call(global.process) === '[object process]' ||
607
608
  navigator.product === 'ReactNative') {
608
- // check nodejs or react native environment
609
609
  return true;
610
610
  }
611
611
  }
@@ -634,9 +634,11 @@
634
634
  };
635
635
 
636
636
  /**
637
- * Sets the given Object as the JSON body of the response.
637
+ * Sets the given value as the JSON body of the response.
638
638
  * @example
639
- * res(json({ foo: 'bar' }))
639
+ * res(json({ key: 'value' }))
640
+ * res(json('Some string'))
641
+ * res(json([1, '2', false, { ok: true }]))
640
642
  */
641
643
  const json = (body) => {
642
644
  return (res) => {
@@ -654,20 +656,21 @@
654
656
  };
655
657
 
656
658
  const useFetch = isNodeProcess() ? require('node-fetch') : window.fetch;
657
- const gracefully = (promise) => {
658
- return promise.then((res) => {
659
- var _a;
660
- if ((_a = res.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('json')) {
661
- return res.json();
662
- }
663
- return res.text();
664
- });
665
- };
666
659
  const augmentRequestInit = (requestInit) => {
667
660
  const headers = new lib.Headers(requestInit.headers);
668
661
  headers.set('x-msw-bypass', 'true');
669
662
  return Object.assign(Object.assign({}, requestInit), { headers: headers.getAllHeaders() });
670
663
  };
664
+ const createFetchRequestParameters = (input) => {
665
+ const { body, method } = input;
666
+ const requestParameters = Object.assign(Object.assign({}, input), { body: undefined });
667
+ if (['GET', 'HEAD'].includes(method)) {
668
+ return requestParameters;
669
+ }
670
+ requestParameters.body =
671
+ typeof body === 'object' ? JSON.stringify(body) : body;
672
+ return requestParameters;
673
+ };
671
674
  /**
672
675
  * Wrapper around the native `window.fetch()` function that performs
673
676
  * a request bypassing MSW. Requests performed using
@@ -676,17 +679,17 @@
676
679
  const fetch = (input, requestInit = {}) => {
677
680
  // Keep the default `window.fetch()` call signature
678
681
  if (typeof input === 'string') {
679
- return gracefully(useFetch(input, augmentRequestInit(requestInit)));
682
+ return useFetch(input, augmentRequestInit(requestInit));
680
683
  }
681
- const { body } = input;
682
- const compliantReq = augmentRequestInit(Object.assign(Object.assign({}, input), { body: typeof body === 'object' ? JSON.stringify(body) : body }));
683
- return gracefully(useFetch(input.url.href, compliantReq));
684
+ const requestParameters = createFetchRequestParameters(input);
685
+ const compliantRequest = augmentRequestInit(requestParameters);
686
+ return useFetch(input.url.href, compliantRequest);
684
687
  };
685
688
 
686
689
  /**
687
690
  * Sets a given text as a "Cotent-Type: text/plain" body of the response.
688
691
  * @example
689
- * res(text('Message'))
692
+ * res(text('message'))
690
693
  */
691
694
  const text = (body) => {
692
695
  return (res) => {
@@ -699,7 +702,7 @@
699
702
  /**
700
703
  * Sets the given XML as the body of the response.
701
704
  * @example
702
- * res(xml('<message>Foo</message>'))
705
+ * res(xml('<key>value</key>'))
703
706
  */
704
707
  const xml = (body) => {
705
708
  return (res) => {
@@ -725,18 +728,18 @@
725
728
  });
726
729
 
727
730
  /*! *****************************************************************************
728
- Copyright (c) Microsoft Corporation. All rights reserved.
729
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
730
- this file except in compliance with the License. You may obtain a copy of the
731
- License at http://www.apache.org/licenses/LICENSE-2.0
731
+ Copyright (c) Microsoft Corporation.
732
732
 
733
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
734
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
735
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
736
- MERCHANTABLITY OR NON-INFRINGEMENT.
733
+ Permission to use, copy, modify, and/or distribute this software for any
734
+ purpose with or without fee is hereby granted.
737
735
 
738
- See the Apache Version 2.0 License for specific language governing permissions
739
- and limitations under the License.
736
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
737
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
738
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
739
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
740
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
741
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
742
+ PERFORMANCE OF THIS SOFTWARE.
740
743
  ***************************************************************************** */
741
744
 
742
745
  function __awaiter(thisArg, _arguments, P, generator) {
@@ -779,7 +782,7 @@
779
782
  * Attempts to resolve a Service Worker instance from a given registration,
780
783
  * regardless of its state (active, installing, waiting).
781
784
  */
782
- const getWorkerByRegistration = (registration, absoluteWorkerUrl) => {
785
+ const getWorkerByRegistration = (registration, absoluteWorkerUrl, findWorker) => {
783
786
  const allStates = [
784
787
  registration.active,
785
788
  registration.installing,
@@ -787,7 +790,7 @@
787
790
  ];
788
791
  const existingStates = allStates.filter(Boolean);
789
792
  const mockWorker = existingStates.find((worker) => {
790
- return worker.scriptURL === absoluteWorkerUrl;
793
+ return findWorker(worker.scriptURL, absoluteWorkerUrl);
791
794
  });
792
795
  return mockWorker || null;
793
796
  };
@@ -804,13 +807,13 @@
804
807
  * Returns an active Service Worker instance.
805
808
  * When not found, registers a new Service Worker.
806
809
  */
807
- const getWorkerInstance = (url, options) => __awaiter(void 0, void 0, void 0, function* () {
808
- // Resolve the absolute Service Worker URL
810
+ const getWorkerInstance = (url, options = {}, findWorker) => __awaiter(void 0, void 0, void 0, function* () {
811
+ // Resolve the absolute Service Worker URL.
809
812
  const absoluteWorkerUrl = getAbsoluteWorkerUrl(url);
810
813
  const [, mockRegistrations] = yield lib$1.until(() => __awaiter(void 0, void 0, void 0, function* () {
811
814
  const registrations = yield navigator.serviceWorker.getRegistrations();
812
815
  return registrations.filter((registration) => {
813
- return getWorkerByRegistration(registration, absoluteWorkerUrl);
816
+ return getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker);
814
817
  });
815
818
  }));
816
819
  if (!navigator.serviceWorker.controller && mockRegistrations.length > 0) {
@@ -824,23 +827,25 @@
824
827
  }
825
828
  const [existingRegistration] = mockRegistrations;
826
829
  if (existingRegistration) {
827
- // Update existing service worker to ensure it's up-to-date
830
+ // When the Service Worker is registered, update it and return the reference.
828
831
  return existingRegistration.update().then(() => {
829
832
  return [
830
- getWorkerByRegistration(existingRegistration, absoluteWorkerUrl),
833
+ getWorkerByRegistration(existingRegistration, absoluteWorkerUrl, findWorker),
831
834
  existingRegistration,
832
835
  ];
833
836
  });
834
837
  }
838
+ // When the Service Worker wasn't found, register it anew and return the reference.
835
839
  const [error, instance] = yield lib$1.until(() => __awaiter(void 0, void 0, void 0, function* () {
836
840
  const registration = yield navigator.serviceWorker.register(url, options);
837
841
  return [
838
842
  // Compare existing worker registration by its worker URL,
839
843
  // to prevent irrelevant workers to resolve here (such as Codesandbox worker).
840
- getWorkerByRegistration(registration, absoluteWorkerUrl),
844
+ getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),
841
845
  registration,
842
846
  ];
843
847
  }));
848
+ // Handle Service Worker registration errors.
844
849
  if (error) {
845
850
  const isWorkerMissing = error.message.includes('(404)');
846
851
  // Produce a custom error message when given a non-existing Service Worker url.
@@ -1018,436 +1023,62 @@ Learn more about creating the Service Worker script: https://mswjs.io/docs/cli/i
1018
1023
  };
1019
1024
  });
1020
1025
 
1021
- function onUnhandledRequest(request, onUnhandledRequest = 'bypass') {
1022
- if (typeof onUnhandledRequest === 'function') {
1023
- onUnhandledRequest(request);
1024
- return;
1025
- }
1026
- const message = `captured a ${request.method} ${request.url} request without a corresponding request handler.`;
1027
- switch (onUnhandledRequest) {
1028
- case 'error': {
1029
- throw new Error(`[MSW] Error: ${message}`);
1030
- }
1031
- case 'warn': {
1032
- console.warn(`[MSW] Warning: ${message}`);
1033
- }
1034
- default:
1035
- return;
1036
- }
1037
- }
1026
+ var punycode = createCommonjsModule(function (module, exports) {
1027
+ (function(root) {
1038
1028
 
1039
- /**
1040
- * Parses a given string into a JSON.
1041
- * Does not throw an exception on an invalid JSON string.
1042
- */
1043
- function jsonParse(str) {
1044
- try {
1045
- return JSON.parse(str);
1046
- }
1047
- catch (error) {
1048
- return undefined;
1049
- }
1050
- }
1029
+ /** Detect free variables */
1030
+ var freeExports = exports &&
1031
+ !exports.nodeType && exports;
1032
+ var freeModule = module &&
1033
+ !module.nodeType && module;
1034
+ var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal;
1035
+ if (
1036
+ freeGlobal.global === freeGlobal ||
1037
+ freeGlobal.window === freeGlobal ||
1038
+ freeGlobal.self === freeGlobal
1039
+ ) {
1040
+ root = freeGlobal;
1041
+ }
1051
1042
 
1052
- /**
1053
- * Returns a parsed JSON from a given valid body string,
1054
- * otherwise returns a given body string as-is.
1055
- */
1056
- function getJsonBody(body) {
1057
- return jsonParse(body) || body;
1058
- }
1043
+ /**
1044
+ * The `punycode` object.
1045
+ * @name punycode
1046
+ * @type Object
1047
+ */
1048
+ var punycode,
1059
1049
 
1060
- function parseRequestBody(body, headers) {
1061
- var _a;
1062
- if (body) {
1063
- // If the intercepted request's body has a JSON Content-Type
1064
- // parse it into an object, otherwise leave as-is.
1065
- const hasJsonContent = (_a = headers === null || headers === void 0 ? void 0 : headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('json');
1066
- if (hasJsonContent && typeof body !== 'object') {
1067
- return getJsonBody(body);
1068
- }
1069
- return body;
1070
- }
1071
- // Return whatever falsey body value is given.
1072
- return body;
1073
- }
1050
+ /** Highest positive signed 32-bit float value */
1051
+ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
1074
1052
 
1075
- function getAllCookies() {
1076
- return parse_1(document.cookie);
1077
- }
1078
- /**
1079
- * Returns relevant document cookies based on the request `credentials` option.
1080
- */
1081
- function getRequestCookies(req) {
1082
- switch (req.credentials) {
1083
- case 'same-origin': {
1084
- // Return document cookies only when requested a resource
1085
- // from the same origin as the current document.
1086
- return location.origin === req.url.origin ? getAllCookies() : {};
1087
- }
1088
- case 'include': {
1089
- // Return all document cookies.
1090
- return getAllCookies();
1091
- }
1092
- default: {
1093
- return {};
1094
- }
1095
- }
1096
- }
1053
+ /** Bootstring parameters */
1054
+ base = 36,
1055
+ tMin = 1,
1056
+ tMax = 26,
1057
+ skew = 38,
1058
+ damp = 700,
1059
+ initialBias = 72,
1060
+ initialN = 128, // 0x80
1061
+ delimiter = '-', // '\x2D'
1097
1062
 
1098
- /**
1099
- * Performs a case-insensitive comparison of two given strings.
1100
- */
1101
- function isStringEqual(actual, expected) {
1102
- return actual.toLowerCase() === expected.toLowerCase();
1103
- }
1063
+ /** Regular expressions */
1064
+ regexPunycode = /^xn--/,
1065
+ regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
1066
+ regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
1104
1067
 
1105
- const handleRequestWith = (context, options) => {
1106
- return (event) => __awaiter(void 0, void 0, void 0, function* () {
1107
- const channel = createBroadcastChannel(event);
1108
- try {
1109
- const message = JSON.parse(event.data, function (key, value) {
1110
- if (key === 'url') {
1111
- return new URL(value);
1112
- }
1113
- // Serialize headers
1114
- if (key === 'headers') {
1115
- return new lib.Headers(value);
1116
- }
1117
- // Prevent empty fields from presering an empty value.
1118
- // It's invalid to perform a GET request with { body: "" }
1119
- if (
1120
- // Check if we are parsing deeper in `event.data.payload`,
1121
- // because this custom JSON parser is invoked for each depth level.
1122
- this.method &&
1123
- isStringEqual(this.method, 'GET') &&
1124
- key === 'body' &&
1125
- value === '') {
1126
- return undefined;
1127
- }
1128
- return value;
1129
- });
1130
- const { type, payload: req } = message;
1131
- // Ignore irrelevant worker message types
1132
- if (type !== 'REQUEST') {
1133
- return null;
1134
- }
1135
- // Parse the request's body based on the "Content-Type" header.
1136
- req.body = parseRequestBody(req.body, req.headers);
1137
- // Set document cookies on the request.
1138
- req.cookies = getRequestCookies(req);
1139
- const { response, handler, publicRequest, parsedRequest, } = yield getResponse(req, context.requestHandlers);
1140
- // Handle a scenario when there is no request handler
1141
- // found for a given request.
1142
- if (!handler) {
1143
- onUnhandledRequest(req, options.onUnhandledRequest);
1144
- return channel.send({ type: 'MOCK_NOT_FOUND' });
1145
- }
1146
- // Handle a scenario when there is a request handler,
1147
- // but it doesn't return any mocked response.
1148
- if (!response) {
1149
- console.warn('[MSW] Expected a mocking resolver function to return a mocked response Object, but got: %s. Original response is going to be used instead.', response);
1150
- return channel.send({ type: 'MOCK_NOT_FOUND' });
1151
- }
1152
- const responseWithSerializedHeaders = Object.assign(Object.assign({}, response), { headers: lib.headersToList(response.headers) });
1153
- if (!options.quiet) {
1154
- setTimeout(() => {
1155
- handler.log(publicRequest, responseWithSerializedHeaders, handler, parsedRequest);
1156
- }, response.delay);
1157
- }
1158
- channel.send({
1159
- type: 'MOCK_SUCCESS',
1160
- payload: responseWithSerializedHeaders,
1161
- });
1162
- }
1163
- catch (error) {
1164
- if (error instanceof NetworkError) {
1165
- // Treat emulated network error differently,
1166
- // as it is an intended exception in a request handler.
1167
- return channel.send({
1168
- type: 'NETWORK_ERROR',
1169
- payload: {
1170
- name: error.name,
1171
- message: error.message,
1172
- },
1173
- });
1174
- }
1175
- // Treat all the other exceptions in a request handler
1176
- // as unintended, alerting that there is a problem needs fixing.
1177
- channel.send({
1178
- type: 'INTERNAL_ERROR',
1179
- payload: {
1180
- status: 500,
1181
- body: JSON.stringify({
1182
- errorType: error.constructor.name,
1183
- message: error.message,
1184
- location: error.stack,
1185
- }),
1186
- },
1187
- });
1188
- }
1189
- });
1190
- };
1068
+ /** Error messages */
1069
+ errors = {
1070
+ 'overflow': 'Overflow: input needs wider integers to process',
1071
+ 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
1072
+ 'invalid-input': 'Invalid input'
1073
+ },
1191
1074
 
1192
- function requestIntegrityCheck(context, serviceWorker) {
1193
- return __awaiter(this, void 0, void 0, function* () {
1194
- // Signal Service Worker to report back its integrity
1195
- serviceWorker.postMessage('INTEGRITY_CHECK_REQUEST');
1196
- const { payload: actualChecksum } = yield context.events.once('INTEGRITY_CHECK_RESPONSE');
1197
- // Compare the response from the Service Worker and the
1198
- // global variable set by webpack upon build.
1199
- if (actualChecksum !== "ca2c3cd7453d8c614e2c19db63ede1a1") {
1200
- throw new Error(`Currently active Service Worker (${actualChecksum}) is behind the latest published one (${"ca2c3cd7453d8c614e2c19db63ede1a1"}).`);
1201
- }
1202
- return serviceWorker;
1203
- });
1204
- }
1075
+ /** Convenience shortcuts */
1076
+ baseMinusTMin = base - tMin,
1077
+ floor = Math.floor,
1078
+ stringFromCharCode = String.fromCharCode,
1205
1079
 
1206
- /**
1207
- * Intercepts and defers any requests on the page
1208
- * until the Service Worker instance is ready.
1209
- * Must only be used in a browser.
1210
- */
1211
- function deferNetworkRequestsUntil(predicatePromise) {
1212
- // Defer `XMLHttpRequest` until the Service Worker is ready.
1213
- const originalXhrSend = window.XMLHttpRequest.prototype.send;
1214
- window.XMLHttpRequest.prototype.send = function (...args) {
1215
- lib$1.until(() => predicatePromise).then(() => {
1216
- window.XMLHttpRequest.prototype.send = originalXhrSend;
1217
- this.send(...args);
1218
- });
1219
- };
1220
- // Defer `fetch` requests until the Service Worker is ready.
1221
- const originalFetch = window.fetch;
1222
- window.fetch = (...args) => __awaiter(this, void 0, void 0, function* () {
1223
- yield lib$1.until(() => predicatePromise);
1224
- window.fetch = originalFetch;
1225
- return window.fetch(...args);
1226
- });
1227
- }
1228
-
1229
- const DEFAULT_START_OPTIONS = {
1230
- serviceWorker: {
1231
- url: '/mockServiceWorker.js',
1232
- options: null,
1233
- },
1234
- quiet: false,
1235
- waitUntilReady: true,
1236
- onUnhandledRequest: 'bypass',
1237
- };
1238
- const createStart = (context) => {
1239
- /**
1240
- * Registers and activates the mock Service Worker.
1241
- */
1242
- return function start(options) {
1243
- const resolvedOptions = Object.assign({}, DEFAULT_START_OPTIONS, options);
1244
- const startWorkerInstance = () => __awaiter(this, void 0, void 0, function* () {
1245
- if (!('serviceWorker' in navigator)) {
1246
- console.error(`[MSW] Failed to register a Service Worker: this browser does not support Service Workers (see https://caniuse.com/serviceworkers), or your application is running on an insecure host (consider using HTTPS for custom hostnames).`);
1247
- return null;
1248
- }
1249
- // Remove all previously existing event listeners.
1250
- // This way none of the listeners persists between Fast refresh
1251
- // of the application's code.
1252
- context.events.removeAllListeners();
1253
- context.events.addListener(navigator.serviceWorker, 'message', handleRequestWith(context, resolvedOptions));
1254
- const [, instance] = yield lib$1.until(() => getWorkerInstance(resolvedOptions.serviceWorker.url, resolvedOptions.serviceWorker.options));
1255
- if (!instance) {
1256
- return null;
1257
- }
1258
- const [worker, registration] = instance;
1259
- if (!worker) {
1260
- return null;
1261
- }
1262
- context.worker = worker;
1263
- context.registration = registration;
1264
- context.events.addListener(window, 'beforeunload', () => {
1265
- if (worker.state !== 'redundant') {
1266
- // Notify the Service Worker that this client has closed.
1267
- // Internally, it's similar to disabling the mocking, only
1268
- // client close event has a handler that self-terminates
1269
- // the Service Worker when there are no open clients.
1270
- worker.postMessage('CLIENT_CLOSED');
1271
- }
1272
- });
1273
- // Check if the active Service Worker is the latest published one
1274
- const [integrityError] = yield lib$1.until(() => requestIntegrityCheck(context, worker));
1275
- if (integrityError) {
1276
- console.error(`\
1277
- [MSW] Detected outdated Service Worker: ${integrityError.message}
1278
-
1279
- The mocking is still enabled, but it's highly recommended that you update your Service Worker by running:
1280
-
1281
- $ npx msw init <PUBLIC_DIR>
1282
-
1283
- This is necessary to ensure that the Service Worker is in sync with the library to guarantee its stability.
1284
- If this message still persists after updating, please report an issue: https://github.com/open-draft/msw/issues\
1285
- `);
1286
- }
1287
- // Signal the Service Worker to enable requests interception
1288
- const [activationError] = yield lib$1.until(() => activateMocking(context, options));
1289
- if (activationError) {
1290
- console.error('Failed to enable mocking', activationError);
1291
- return null;
1292
- }
1293
- return registration;
1294
- });
1295
- const workerRegistration = startWorkerInstance();
1296
- // Defer any network requests until the Service Worker instance is ready.
1297
- // This prevents a race condition between the Service Worker registration
1298
- // and application's runtime requests (i.e. requests on mount).
1299
- if (resolvedOptions.waitUntilReady) {
1300
- deferNetworkRequestsUntil(workerRegistration);
1301
- }
1302
- return workerRegistration;
1303
- };
1304
- };
1305
-
1306
- const createStop = (context) => {
1307
- /**
1308
- * Signal the Service Worker to disable mocking for this client.
1309
- * Use this an an explicit way to stop the mocking, while preserving
1310
- * the worker-client relation. Does not affect the worker's lifecycle.
1311
- */
1312
- return function stop() {
1313
- var _a;
1314
- (_a = context.worker) === null || _a === void 0 ? void 0 : _a.postMessage('MOCK_DEACTIVATE');
1315
- context.events.removeAllListeners();
1316
- };
1317
- };
1318
-
1319
- function use(currentHandlers, ...handlers) {
1320
- currentHandlers.unshift(...handlers);
1321
- }
1322
- function restoreHandlers(handlers) {
1323
- handlers.forEach((handler) => {
1324
- if ('shouldSkip' in handler) {
1325
- handler.shouldSkip = false;
1326
- }
1327
- });
1328
- }
1329
- function resetHandlers(initialHandlers, ...nextHandlers) {
1330
- return nextHandlers.length > 0 ? [...nextHandlers] : [...initialHandlers];
1331
- }
1332
-
1333
- // Declare the list of event handlers on the module's scope
1334
- // so it persists between Fash refreshes of the application's code.
1335
- let listeners = [];
1336
- function setupWorker(...requestHandlers) {
1337
- const context = {
1338
- worker: null,
1339
- registration: null,
1340
- requestHandlers: [...requestHandlers],
1341
- events: {
1342
- addListener(target, event, callback) {
1343
- target.addEventListener(event, callback);
1344
- listeners.push({ event, target, callback });
1345
- return () => {
1346
- target.removeEventListener(event, callback);
1347
- };
1348
- },
1349
- removeAllListeners() {
1350
- for (const { target, event, callback } of listeners) {
1351
- target.removeEventListener(event, callback);
1352
- }
1353
- listeners = [];
1354
- },
1355
- once(type) {
1356
- const bindings = [];
1357
- return new Promise((resolve, reject) => {
1358
- const handleIncomingMessage = (event) => {
1359
- try {
1360
- const message = JSON.parse(event.data);
1361
- if (message.type === type) {
1362
- resolve(message);
1363
- }
1364
- }
1365
- catch (error) {
1366
- reject(error);
1367
- }
1368
- };
1369
- bindings.push(context.events.addListener(navigator.serviceWorker, 'message', handleIncomingMessage), context.events.addListener(navigator.serviceWorker, 'messageerror', reject));
1370
- }).finally(() => {
1371
- bindings.forEach((unbind) => unbind());
1372
- });
1373
- },
1374
- },
1375
- };
1376
- // Error when attempting to run this function in a NodeJS environment.
1377
- if (isNodeProcess()) {
1378
- throw new Error('[MSW] Failed to execute `setupWorker` in a non-browser environment. Consider using `setupServer` for NodeJS environment instead.');
1379
- }
1380
- return {
1381
- start: createStart(context),
1382
- stop: createStop(context),
1383
- use(...handlers) {
1384
- use(context.requestHandlers, ...handlers);
1385
- },
1386
- restoreHandlers() {
1387
- restoreHandlers(context.requestHandlers);
1388
- },
1389
- resetHandlers(...nextHandlers) {
1390
- context.requestHandlers = resetHandlers(requestHandlers, ...nextHandlers);
1391
- },
1392
- };
1393
- }
1394
-
1395
- var punycode = createCommonjsModule(function (module, exports) {
1396
- (function(root) {
1397
-
1398
- /** Detect free variables */
1399
- var freeExports = exports &&
1400
- !exports.nodeType && exports;
1401
- var freeModule = module &&
1402
- !module.nodeType && module;
1403
- var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal;
1404
- if (
1405
- freeGlobal.global === freeGlobal ||
1406
- freeGlobal.window === freeGlobal ||
1407
- freeGlobal.self === freeGlobal
1408
- ) {
1409
- root = freeGlobal;
1410
- }
1411
-
1412
- /**
1413
- * The `punycode` object.
1414
- * @name punycode
1415
- * @type Object
1416
- */
1417
- var punycode,
1418
-
1419
- /** Highest positive signed 32-bit float value */
1420
- maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
1421
-
1422
- /** Bootstring parameters */
1423
- base = 36,
1424
- tMin = 1,
1425
- tMax = 26,
1426
- skew = 38,
1427
- damp = 700,
1428
- initialBias = 72,
1429
- initialN = 128, // 0x80
1430
- delimiter = '-', // '\x2D'
1431
-
1432
- /** Regular expressions */
1433
- regexPunycode = /^xn--/,
1434
- regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
1435
- regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
1436
-
1437
- /** Error messages */
1438
- errors = {
1439
- 'overflow': 'Overflow: input needs wider integers to process',
1440
- 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
1441
- 'invalid-input': 'Invalid input'
1442
- },
1443
-
1444
- /** Convenience shortcuts */
1445
- baseMinusTMin = base - tMin,
1446
- floor = Math.floor,
1447
- stringFromCharCode = String.fromCharCode,
1448
-
1449
- /** Temporary variable */
1450
- key;
1080
+ /** Temporary variable */
1081
+ key;
1451
1082
 
1452
1083
  /*--------------------------------------------------------------------------*/
1453
1084
 
@@ -2674,65 +2305,507 @@ If this message still persists after updating, please report an issue: https://g
2674
2305
  srcPath.unshift('');
2675
2306
  }
2676
2307
 
2677
- if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
2678
- srcPath.push('');
2679
- }
2308
+ if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
2309
+ srcPath.push('');
2310
+ }
2311
+
2312
+ var isAbsolute = srcPath[0] === '' ||
2313
+ (srcPath[0] && srcPath[0].charAt(0) === '/');
2314
+
2315
+ // put the host back
2316
+ if (psychotic) {
2317
+ result.hostname = result.host = isAbsolute ? '' :
2318
+ srcPath.length ? srcPath.shift() : '';
2319
+ //occationaly the auth can get stuck only in host
2320
+ //this especially happens in cases like
2321
+ //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
2322
+ var authInHost = result.host && result.host.indexOf('@') > 0 ?
2323
+ result.host.split('@') : false;
2324
+ if (authInHost) {
2325
+ result.auth = authInHost.shift();
2326
+ result.host = result.hostname = authInHost.shift();
2327
+ }
2328
+ }
2329
+
2330
+ mustEndAbs = mustEndAbs || (result.host && srcPath.length);
2331
+
2332
+ if (mustEndAbs && !isAbsolute) {
2333
+ srcPath.unshift('');
2334
+ }
2335
+
2336
+ if (!srcPath.length) {
2337
+ result.pathname = null;
2338
+ result.path = null;
2339
+ } else {
2340
+ result.pathname = srcPath.join('/');
2341
+ }
2342
+
2343
+ //to support request.http
2344
+ if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
2345
+ result.path = (result.pathname ? result.pathname : '') +
2346
+ (result.search ? result.search : '');
2347
+ }
2348
+ result.auth = relative.auth || result.auth;
2349
+ result.slashes = result.slashes || relative.slashes;
2350
+ result.href = result.format();
2351
+ return result;
2352
+ };
2353
+
2354
+ Url.prototype.parseHost = function() {
2355
+ var host = this.host;
2356
+ var port = portPattern.exec(host);
2357
+ if (port) {
2358
+ port = port[0];
2359
+ if (port !== ':') {
2360
+ this.port = port.substr(1);
2361
+ }
2362
+ host = host.substr(0, host.length - port.length);
2363
+ }
2364
+ if (host) this.hostname = host;
2365
+ };
2366
+
2367
+ /**
2368
+ * Returns a relative URL if the given request URL is relative to the current origin.
2369
+ * Otherwise returns an absolute URL.
2370
+ */
2371
+ const getPublicUrlFromRequest = (request) => {
2372
+ return request.referrer.startsWith(request.url.origin)
2373
+ ? request.url.pathname
2374
+ : format({
2375
+ protocol: request.url.protocol,
2376
+ host: request.url.host,
2377
+ pathname: request.url.pathname,
2378
+ });
2379
+ };
2380
+
2381
+ function onUnhandledRequest(request, onUnhandledRequest = 'bypass') {
2382
+ if (typeof onUnhandledRequest === 'function') {
2383
+ onUnhandledRequest(request);
2384
+ return;
2385
+ }
2386
+ const publicUrl = getPublicUrlFromRequest(request);
2387
+ const message = `captured a ${request.method} ${request.url} request without a corresponding request handler.
2388
+
2389
+ If you wish to intercept this request, consider creating a request handler for it:
2390
+
2391
+ rest.${request.method.toLowerCase()}('${publicUrl}', (req, res, ctx) => {
2392
+ return res(ctx.text('body'))
2393
+ })`;
2394
+ switch (onUnhandledRequest) {
2395
+ case 'error': {
2396
+ throw new Error(`[MSW] Error: ${message}`);
2397
+ }
2398
+ case 'warn': {
2399
+ console.warn(`[MSW] Warning: ${message}`);
2400
+ }
2401
+ default:
2402
+ return;
2403
+ }
2404
+ }
2405
+
2406
+ /**
2407
+ * Parses a given string into a JSON.
2408
+ * Does not throw an exception on an invalid JSON string.
2409
+ */
2410
+ function jsonParse(str) {
2411
+ try {
2412
+ return JSON.parse(str);
2413
+ }
2414
+ catch (error) {
2415
+ return undefined;
2416
+ }
2417
+ }
2418
+
2419
+ /**
2420
+ * Parses a given request/response body based on the `Content-Type` header.
2421
+ */
2422
+ function parseBody(body, headers) {
2423
+ var _a;
2424
+ if (body) {
2425
+ // If the intercepted request's body has a JSON Content-Type
2426
+ // parse it into an object, otherwise leave as-is.
2427
+ const hasJsonContent = (_a = headers === null || headers === void 0 ? void 0 : headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('json');
2428
+ if (hasJsonContent && typeof body !== 'object') {
2429
+ return jsonParse(body) || body;
2430
+ }
2431
+ return body;
2432
+ }
2433
+ // Return whatever falsey body value is given.
2434
+ return body;
2435
+ }
2436
+
2437
+ function getAllCookies() {
2438
+ return parse_1(document.cookie);
2439
+ }
2440
+ /**
2441
+ * Returns relevant document cookies based on the request `credentials` option.
2442
+ */
2443
+ function getRequestCookies(req) {
2444
+ switch (req.credentials) {
2445
+ case 'same-origin': {
2446
+ // Return document cookies only when requested a resource
2447
+ // from the same origin as the current document.
2448
+ return location.origin === req.url.origin ? getAllCookies() : {};
2449
+ }
2450
+ case 'include': {
2451
+ // Return all document cookies.
2452
+ return getAllCookies();
2453
+ }
2454
+ default: {
2455
+ return {};
2456
+ }
2457
+ }
2458
+ }
2459
+
2460
+ /**
2461
+ * Performs a case-insensitive comparison of two given strings.
2462
+ */
2463
+ function isStringEqual(actual, expected) {
2464
+ return actual.toLowerCase() === expected.toLowerCase();
2465
+ }
2466
+
2467
+ const handleRequestWith = (context, options) => {
2468
+ return (event) => __awaiter(void 0, void 0, void 0, function* () {
2469
+ const channel = createBroadcastChannel(event);
2470
+ try {
2471
+ const message = JSON.parse(event.data, function (key, value) {
2472
+ if (key === 'url') {
2473
+ return new URL(value);
2474
+ }
2475
+ // Serialize headers
2476
+ if (key === 'headers') {
2477
+ return new lib.Headers(value);
2478
+ }
2479
+ // Prevent empty fields from presering an empty value.
2480
+ // It's invalid to perform a GET request with { body: "" }
2481
+ if (
2482
+ // Check if we are parsing deeper in `event.data.payload`,
2483
+ // because this custom JSON parser is invoked for each depth level.
2484
+ this.method &&
2485
+ isStringEqual(this.method, 'GET') &&
2486
+ key === 'body' &&
2487
+ value === '') {
2488
+ return undefined;
2489
+ }
2490
+ return value;
2491
+ });
2492
+ const { type, payload: req } = message;
2493
+ // Ignore irrelevant worker message types
2494
+ if (type !== 'REQUEST') {
2495
+ return null;
2496
+ }
2497
+ // Parse the request's body based on the "Content-Type" header.
2498
+ req.body = parseBody(req.body, req.headers);
2499
+ // Set document cookies on the request.
2500
+ req.cookies = getRequestCookies(req);
2501
+ const { response, handler, publicRequest, parsedRequest, } = yield getResponse(req, context.requestHandlers);
2502
+ // Handle a scenario when there is no request handler
2503
+ // found for a given request.
2504
+ if (!handler) {
2505
+ onUnhandledRequest(req, options.onUnhandledRequest);
2506
+ return channel.send({ type: 'MOCK_NOT_FOUND' });
2507
+ }
2508
+ // Handle a scenario when there is a request handler,
2509
+ // but it doesn't return any mocked response.
2510
+ if (!response) {
2511
+ console.warn('[MSW] Expected a mocking resolver function to return a mocked response Object, but got: %s. Original response is going to be used instead.', response);
2512
+ return channel.send({ type: 'MOCK_NOT_FOUND' });
2513
+ }
2514
+ const responseWithSerializedHeaders = Object.assign(Object.assign({}, response), { headers: lib.headersToList(response.headers) });
2515
+ if (!options.quiet) {
2516
+ setTimeout(() => {
2517
+ handler.log(publicRequest, responseWithSerializedHeaders, handler, parsedRequest);
2518
+ }, response.delay);
2519
+ }
2520
+ channel.send({
2521
+ type: 'MOCK_SUCCESS',
2522
+ payload: responseWithSerializedHeaders,
2523
+ });
2524
+ }
2525
+ catch (error) {
2526
+ if (error instanceof NetworkError) {
2527
+ // Treat emulated network error differently,
2528
+ // as it is an intended exception in a request handler.
2529
+ return channel.send({
2530
+ type: 'NETWORK_ERROR',
2531
+ payload: {
2532
+ name: error.name,
2533
+ message: error.message,
2534
+ },
2535
+ });
2536
+ }
2537
+ // Treat all the other exceptions in a request handler
2538
+ // as unintended, alerting that there is a problem needs fixing.
2539
+ channel.send({
2540
+ type: 'INTERNAL_ERROR',
2541
+ payload: {
2542
+ status: 500,
2543
+ body: JSON.stringify({
2544
+ errorType: error.constructor.name,
2545
+ message: error.message,
2546
+ location: error.stack,
2547
+ }),
2548
+ },
2549
+ });
2550
+ }
2551
+ });
2552
+ };
2553
+
2554
+ function requestIntegrityCheck(context, serviceWorker) {
2555
+ return __awaiter(this, void 0, void 0, function* () {
2556
+ // Signal Service Worker to report back its integrity
2557
+ serviceWorker.postMessage('INTEGRITY_CHECK_REQUEST');
2558
+ const { payload: actualChecksum } = yield context.events.once('INTEGRITY_CHECK_RESPONSE');
2559
+ // Compare the response from the Service Worker and the
2560
+ // global variable set by webpack upon build.
2561
+ if (actualChecksum !== "d1e0e502f550d40a34bee90822e4bf98") {
2562
+ throw new Error(`Currently active Service Worker (${actualChecksum}) is behind the latest published one (${"d1e0e502f550d40a34bee90822e4bf98"}).`);
2563
+ }
2564
+ return serviceWorker;
2565
+ });
2566
+ }
2567
+
2568
+ /**
2569
+ * Intercepts and defers any requests on the page
2570
+ * until the Service Worker instance is ready.
2571
+ * Must only be used in a browser.
2572
+ */
2573
+ function deferNetworkRequestsUntil(predicatePromise) {
2574
+ // Defer any `XMLHttpRequest` requests until the Service Worker is ready.
2575
+ const originalXhrSend = window.XMLHttpRequest.prototype.send;
2576
+ window.XMLHttpRequest.prototype.send = function (...args) {
2577
+ // Keep this function synchronous to comply with `XMLHttpRequest.prototype.send`,
2578
+ // because that method is always synchronous.
2579
+ lib$1.until(() => predicatePromise).then(() => {
2580
+ window.XMLHttpRequest.prototype.send = originalXhrSend;
2581
+ this.send(...args);
2582
+ });
2583
+ };
2584
+ // Defer any `fetch` requests until the Service Worker is ready.
2585
+ const originalFetch = window.fetch;
2586
+ window.fetch = (...args) => __awaiter(this, void 0, void 0, function* () {
2587
+ yield lib$1.until(() => predicatePromise);
2588
+ window.fetch = originalFetch;
2589
+ return window.fetch(...args);
2590
+ });
2591
+ }
2592
+
2593
+ function isObject(obj) {
2594
+ return typeof obj === 'object';
2595
+ }
2596
+ /**
2597
+ * Deeply merges two given objects with the right one
2598
+ * having a priority during property assignment.
2599
+ */
2600
+ function mergeRight(a, b) {
2601
+ const result = Object.assign({}, a);
2602
+ Object.entries(b).forEach(([key, value]) => {
2603
+ const existingValue = result[key];
2604
+ if (Array.isArray(existingValue) && Array.isArray(value)) {
2605
+ result[key] = existingValue.concat(value);
2606
+ return;
2607
+ }
2608
+ if (isObject(existingValue) && isObject(value)) {
2609
+ result[key] = mergeRight(existingValue, value);
2610
+ return;
2611
+ }
2612
+ result[key] = value;
2613
+ });
2614
+ return result;
2615
+ }
2616
+
2617
+ const DEFAULT_START_OPTIONS = {
2618
+ serviceWorker: {
2619
+ url: '/mockServiceWorker.js',
2620
+ options: null,
2621
+ },
2622
+ quiet: false,
2623
+ waitUntilReady: true,
2624
+ onUnhandledRequest: 'bypass',
2625
+ findWorker: (scriptURL, mockServiceWorkerUrl) => scriptURL === mockServiceWorkerUrl,
2626
+ };
2627
+ const createStart = (context) => {
2628
+ /**
2629
+ * Registers and activates the mock Service Worker.
2630
+ */
2631
+ return function start(options) {
2632
+ const resolvedOptions = mergeRight(DEFAULT_START_OPTIONS, options || {});
2633
+ const startWorkerInstance = () => __awaiter(this, void 0, void 0, function* () {
2634
+ if (!('serviceWorker' in navigator)) {
2635
+ console.error(`[MSW] Failed to register a Service Worker: this browser does not support Service Workers (see https://caniuse.com/serviceworkers), or your application is running on an insecure host (consider using HTTPS for custom hostnames).`);
2636
+ return null;
2637
+ }
2638
+ // Remove all previously existing event listeners.
2639
+ // This way none of the listeners persists between Fast refresh
2640
+ // of the application's code.
2641
+ context.events.removeAllListeners();
2642
+ context.events.addListener(navigator.serviceWorker, 'message', handleRequestWith(context, resolvedOptions));
2643
+ const [, instance] = yield lib$1.until(() => getWorkerInstance(resolvedOptions.serviceWorker.url, resolvedOptions.serviceWorker.options, resolvedOptions.findWorker));
2644
+ if (!instance) {
2645
+ return null;
2646
+ }
2647
+ const [worker, registration] = instance;
2648
+ if (!worker) {
2649
+ if (options === null || options === void 0 ? void 0 : options.findWorker) {
2650
+ console.error(`\
2651
+ [MSW] Failed to locate the Service Worker registration using a custom "findWorker" predicate.
2680
2652
 
2681
- var isAbsolute = srcPath[0] === '' ||
2682
- (srcPath[0] && srcPath[0].charAt(0) === '/');
2653
+ Please ensure that the custom predicate properly locates the Service Worker registration at "${resolvedOptions.serviceWorker.url}".
2654
+ More details: https://mswjs.io/docs/api/setup-worker/start#findworker
2655
+ `);
2656
+ }
2657
+ else {
2658
+ console.error(`\
2659
+ [MSW] Failed to locate the Service Worker registration.
2683
2660
 
2684
- // put the host back
2685
- if (psychotic) {
2686
- result.hostname = result.host = isAbsolute ? '' :
2687
- srcPath.length ? srcPath.shift() : '';
2688
- //occationaly the auth can get stuck only in host
2689
- //this especially happens in cases like
2690
- //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
2691
- var authInHost = result.host && result.host.indexOf('@') > 0 ?
2692
- result.host.split('@') : false;
2693
- if (authInHost) {
2694
- result.auth = authInHost.shift();
2695
- result.host = result.hostname = authInHost.shift();
2696
- }
2697
- }
2661
+ This most likely means that the worker script URL "${resolvedOptions.serviceWorker.url}" cannot resolve against the actual public hostname (${location.host}). This may happen if your application runs behind a proxy, or has a dynamic hostname.
2698
2662
 
2699
- mustEndAbs = mustEndAbs || (result.host && srcPath.length);
2663
+ Please consider using a custom "serviceWorker.url" option to point to the actual worker script location, or a custom "findWorker" option to resolve the Service Worker registration manually. More details: https://mswjs.io/docs/api/setup-worker/start`);
2664
+ }
2665
+ return null;
2666
+ }
2667
+ context.worker = worker;
2668
+ context.registration = registration;
2669
+ context.events.addListener(window, 'beforeunload', () => {
2670
+ if (worker.state !== 'redundant') {
2671
+ // Notify the Service Worker that this client has closed.
2672
+ // Internally, it's similar to disabling the mocking, only
2673
+ // client close event has a handler that self-terminates
2674
+ // the Service Worker when there are no open clients.
2675
+ worker.postMessage('CLIENT_CLOSED');
2676
+ }
2677
+ // Make sure we're always clearing the interval - there are reports that not doing this can
2678
+ // cause memory leaks in headless browser environments.
2679
+ window.clearInterval(context.keepAliveInterval);
2680
+ });
2681
+ // Check if the active Service Worker is the latest published one
2682
+ const [integrityError] = yield lib$1.until(() => requestIntegrityCheck(context, worker));
2683
+ if (integrityError) {
2684
+ console.error(`\
2685
+ [MSW] Detected outdated Service Worker: ${integrityError.message}
2700
2686
 
2701
- if (mustEndAbs && !isAbsolute) {
2702
- srcPath.unshift('');
2703
- }
2687
+ The mocking is still enabled, but it's highly recommended that you update your Service Worker by running:
2704
2688
 
2705
- if (!srcPath.length) {
2706
- result.pathname = null;
2707
- result.path = null;
2708
- } else {
2709
- result.pathname = srcPath.join('/');
2710
- }
2689
+ $ npx msw init <PUBLIC_DIR>
2711
2690
 
2712
- //to support request.http
2713
- if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
2714
- result.path = (result.pathname ? result.pathname : '') +
2715
- (result.search ? result.search : '');
2716
- }
2717
- result.auth = relative.auth || result.auth;
2718
- result.slashes = result.slashes || relative.slashes;
2719
- result.href = result.format();
2720
- return result;
2691
+ This is necessary to ensure that the Service Worker is in sync with the library to guarantee its stability.
2692
+ If this message still persists after updating, please report an issue: https://github.com/open-draft/msw/issues\
2693
+ `);
2694
+ }
2695
+ // Signal the Service Worker to enable requests interception
2696
+ const [activationError] = yield lib$1.until(() => activateMocking(context, options));
2697
+ if (activationError) {
2698
+ console.error('Failed to enable mocking', activationError);
2699
+ return null;
2700
+ }
2701
+ context.keepAliveInterval = window.setInterval(() => worker.postMessage('KEEPALIVE_REQUEST'), 5000);
2702
+ return registration;
2703
+ });
2704
+ const workerRegistration = startWorkerInstance();
2705
+ // Defer any network requests until the Service Worker instance is ready.
2706
+ // This prevents a race condition between the Service Worker registration
2707
+ // and application's runtime requests (i.e. requests on mount).
2708
+ if (resolvedOptions.waitUntilReady) {
2709
+ deferNetworkRequestsUntil(workerRegistration);
2710
+ }
2711
+ return workerRegistration;
2712
+ };
2721
2713
  };
2722
2714
 
2723
- Url.prototype.parseHost = function() {
2724
- var host = this.host;
2725
- var port = portPattern.exec(host);
2726
- if (port) {
2727
- port = port[0];
2728
- if (port !== ':') {
2729
- this.port = port.substr(1);
2730
- }
2731
- host = host.substr(0, host.length - port.length);
2732
- }
2733
- if (host) this.hostname = host;
2715
+ const createStop = (context) => {
2716
+ /**
2717
+ * Signal the Service Worker to disable mocking for this client.
2718
+ * Use this an an explicit way to stop the mocking, while preserving
2719
+ * the worker-client relation. Does not affect the worker's lifecycle.
2720
+ */
2721
+ return function stop() {
2722
+ var _a;
2723
+ (_a = context.worker) === null || _a === void 0 ? void 0 : _a.postMessage('MOCK_DEACTIVATE');
2724
+ context.events.removeAllListeners();
2725
+ window.clearInterval(context.keepAliveInterval);
2726
+ };
2734
2727
  };
2735
2728
 
2729
+ function use(currentHandlers, ...handlers) {
2730
+ currentHandlers.unshift(...handlers);
2731
+ }
2732
+ function restoreHandlers(handlers) {
2733
+ handlers.forEach((handler) => {
2734
+ if ('shouldSkip' in handler) {
2735
+ handler.shouldSkip = false;
2736
+ }
2737
+ });
2738
+ }
2739
+ function resetHandlers(initialHandlers, ...nextHandlers) {
2740
+ return nextHandlers.length > 0 ? [...nextHandlers] : [...initialHandlers];
2741
+ }
2742
+
2743
+ // Declare the list of event handlers on the module's scope
2744
+ // so it persists between Fash refreshes of the application's code.
2745
+ let listeners = [];
2746
+ function setupWorker(...requestHandlers) {
2747
+ requestHandlers.forEach((handler) => {
2748
+ if (Array.isArray(handler))
2749
+ throw new Error(`[MSW] Failed to call "setupWorker" given an Array of request handlers (setupWorker([a, b])), expected to receive each handler individually: setupWorker(a, b).`);
2750
+ });
2751
+ const context = {
2752
+ worker: null,
2753
+ registration: null,
2754
+ requestHandlers: [...requestHandlers],
2755
+ events: {
2756
+ addListener(target, event, callback) {
2757
+ target.addEventListener(event, callback);
2758
+ listeners.push({ event, target, callback });
2759
+ return () => {
2760
+ target.removeEventListener(event, callback);
2761
+ };
2762
+ },
2763
+ removeAllListeners() {
2764
+ for (const { target, event, callback } of listeners) {
2765
+ target.removeEventListener(event, callback);
2766
+ }
2767
+ listeners = [];
2768
+ },
2769
+ once(type) {
2770
+ const bindings = [];
2771
+ return new Promise((resolve, reject) => {
2772
+ const handleIncomingMessage = (event) => {
2773
+ try {
2774
+ const message = JSON.parse(event.data);
2775
+ if (message.type === type) {
2776
+ resolve(message);
2777
+ }
2778
+ }
2779
+ catch (error) {
2780
+ reject(error);
2781
+ }
2782
+ };
2783
+ bindings.push(context.events.addListener(navigator.serviceWorker, 'message', handleIncomingMessage), context.events.addListener(navigator.serviceWorker, 'messageerror', reject));
2784
+ }).finally(() => {
2785
+ bindings.forEach((unbind) => unbind());
2786
+ });
2787
+ },
2788
+ },
2789
+ };
2790
+ // Error when attempting to run this function in a NodeJS environment.
2791
+ if (isNodeProcess()) {
2792
+ throw new Error('[MSW] Failed to execute `setupWorker` in a non-browser environment. Consider using `setupServer` for NodeJS environment instead.');
2793
+ }
2794
+ return {
2795
+ start: createStart(context),
2796
+ stop: createStop(context),
2797
+ use(...handlers) {
2798
+ use(context.requestHandlers, ...handlers);
2799
+ },
2800
+ restoreHandlers() {
2801
+ restoreHandlers(context.requestHandlers);
2802
+ },
2803
+ resetHandlers(...nextHandlers) {
2804
+ context.requestHandlers = resetHandlers(requestHandlers, ...nextHandlers);
2805
+ },
2806
+ };
2807
+ }
2808
+
2736
2809
  /**
2737
2810
  * Formats a mocked request for introspection in browser's console.
2738
2811
  */
@@ -2744,12 +2817,10 @@ If this message still persists after updating, please report an issue: https://g
2744
2817
  * Formats a mocked response for introspection in browser's console.
2745
2818
  */
2746
2819
  function prepareResponse(res) {
2747
- var _a;
2748
- const resHeaders = lib.listToHeaders(res.headers);
2820
+ const responseHeaders = lib.listToHeaders(res.headers);
2749
2821
  return Object.assign(Object.assign({}, res), {
2750
2822
  // Parse a response JSON body for preview in the logs
2751
- body: ((_a = resHeaders.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('json')) ? getJsonBody(res.body)
2752
- : res.body });
2823
+ body: parseBody(res.body, responseHeaders) });
2753
2824
  }
2754
2825
 
2755
2826
  function getTimestamp() {
@@ -2826,10 +2897,10 @@ If this message still persists after updating, please report an issue: https://g
2826
2897
  });
2827
2898
 
2828
2899
  /**
2829
- * Resolves a relative URL to the absolute URL with the same hostname.
2900
+ * Returns an absolute URL based on the given relative URL, if possible.
2830
2901
  * Ignores regular expressions.
2831
2902
  */
2832
- const resolveRelativeUrl = (mask) => {
2903
+ const getAbsoluteUrl = (mask) => {
2833
2904
  // Global `location` object doesn't exist in Node.
2834
2905
  // Relative request predicate URL cannot become absolute.
2835
2906
  const hasLocation = typeof location !== 'undefined';
@@ -2840,17 +2911,21 @@ If this message still persists after updating, please report an issue: https://g
2840
2911
 
2841
2912
  /**
2842
2913
  * Converts a given request handler mask into a URL, if given a valid URL string.
2843
- * Otherwise, returns the mask as-is.
2844
2914
  */
2845
- function resolveMask(mask) {
2846
- if (mask instanceof RegExp) {
2915
+ function getUrlByMask(mask) {
2916
+ /**
2917
+ * If a string mask contains an asterisk (wildcard), return it as-is.
2918
+ * Converting a URL-like path string into an actual URL is misleading.
2919
+ * @see https://github.com/mswjs/msw/issues/357
2920
+ */
2921
+ if (mask instanceof RegExp || mask.includes('*')) {
2847
2922
  return mask;
2848
2923
  }
2849
2924
  try {
2850
2925
  // Attempt to create a URL instance out of the mask string.
2851
2926
  // Resolve mask to an absolute URL, because even a valid relative URL
2852
2927
  // cannot be converted into the URL instance (required absolute URL only).
2853
- return new URL(resolveRelativeUrl(mask));
2928
+ return new URL(getAbsoluteUrl(mask));
2854
2929
  }
2855
2930
  catch (error) {
2856
2931
  // Otherwise, the mask is a path string.
@@ -2863,7 +2938,7 @@ If this message still persists after updating, please report an issue: https://g
2863
2938
  ? getCleanUrl_1.getCleanUrl(resolvedMask)
2864
2939
  : resolvedMask instanceof RegExp
2865
2940
  ? resolvedMask
2866
- : resolveRelativeUrl(resolvedMask);
2941
+ : getAbsoluteUrl(resolvedMask);
2867
2942
  }
2868
2943
 
2869
2944
  /**
@@ -2871,13 +2946,14 @@ If this message still persists after updating, please report an issue: https://g
2871
2946
  * against a mask.
2872
2947
  */
2873
2948
  function matchRequestUrl(url, mask) {
2874
- const resolvedMask = resolveMask(mask);
2949
+ const resolvedMask = getUrlByMask(mask);
2875
2950
  const cleanMask = getCleanMask(resolvedMask);
2876
2951
  const cleanRequestUrl = getCleanUrl_1.getCleanUrl(url);
2877
2952
  return match(cleanMask, cleanRequestUrl);
2878
2953
  }
2879
2954
 
2880
2955
  (function (RESTMethods) {
2956
+ RESTMethods["HEAD"] = "HEAD";
2881
2957
  RESTMethods["GET"] = "GET";
2882
2958
  RESTMethods["POST"] = "POST";
2883
2959
  RESTMethods["PUT"] = "PUT";
@@ -2898,7 +2974,7 @@ If this message still persists after updating, please report an issue: https://g
2898
2974
  };
2899
2975
  const createRestHandler = (method) => {
2900
2976
  return (mask, resolver) => {
2901
- const resolvedMask = resolveMask(mask);
2977
+ const resolvedMask = getUrlByMask(mask);
2902
2978
  return {
2903
2979
  parse(req) {
2904
2980
  // Match the request during parsing to prevent matching it twice
@@ -2937,14 +3013,7 @@ ${queryParams
2937
3013
  })\
2938
3014
  `);
2939
3015
  }
2940
- const isRelativeRequest = req.referrer.startsWith(req.url.origin);
2941
- const publicUrl = isRelativeRequest
2942
- ? req.url.pathname
2943
- : format({
2944
- protocol: req.url.protocol,
2945
- host: req.url.host,
2946
- pathname: req.url.pathname,
2947
- });
3016
+ const publicUrl = getPublicUrlFromRequest(req);
2948
3017
  const loggedRequest = prepareRequest(req);
2949
3018
  const loggedResponse = prepareResponse(res);
2950
3019
  console.groupCollapsed('[MSW] %s %s %s (%c%s%c)', getTimestamp(), req.method, publicUrl, `color:${getStatusCodeColor(res.status)}`, res.status, 'color:inherit');
@@ -2960,6 +3029,7 @@ ${queryParams
2960
3029
  };
2961
3030
  };
2962
3031
  const rest = {
3032
+ head: createRestHandler(exports.RESTMethods.HEAD),
2963
3033
  get: createRestHandler(exports.RESTMethods.GET),
2964
3034
  post: createRestHandler(exports.RESTMethods.POST),
2965
3035
  put: createRestHandler(exports.RESTMethods.PUT),
@@ -5975,96 +6045,109 @@ ${queryParams
5975
6045
  function parseQuery(query, definitionOperation = 'query') {
5976
6046
  var _a;
5977
6047
  const ast = parse$1(query);
5978
- const operationDef = ast.definitions.find((def) => def.kind === 'OperationDefinition' &&
5979
- def.operation === definitionOperation);
6048
+ const operationDef = ast.definitions.find((def) => {
6049
+ return (def.kind === 'OperationDefinition' &&
6050
+ (definitionOperation === 'all' || def.operation === definitionOperation));
6051
+ });
5980
6052
  return {
6053
+ operationType: operationDef === null || operationDef === void 0 ? void 0 : operationDef.operation,
5981
6054
  operationName: (_a = operationDef === null || operationDef === void 0 ? void 0 : operationDef.name) === null || _a === void 0 ? void 0 : _a.value,
5982
6055
  };
5983
6056
  }
5984
- const createGraphQLHandler = (operationType, mask) => {
5985
- return (expectedOperation, resolver) => {
5986
- return {
5987
- resolver,
5988
- parse(req) {
5989
- var _a;
5990
- // According to the GraphQL specification, a GraphQL request can be issued
5991
- // using both "GET" and "POST" methods.
5992
- switch (req.method) {
5993
- case 'GET': {
5994
- const query = req.url.searchParams.get('query');
5995
- const variablesString = req.url.searchParams.get('variables') || '';
5996
- if (!query) {
5997
- return null;
5998
- }
5999
- const variables = variablesString
6000
- ? jsonParse(variablesString)
6001
- : {};
6002
- const { operationName } = parseQuery(query, operationType);
6003
- return {
6004
- operationType,
6005
- operationName,
6006
- variables,
6007
- };
6008
- }
6009
- case 'POST': {
6010
- if (!((_a = req.body) === null || _a === void 0 ? void 0 : _a.query)) {
6011
- return null;
6012
- }
6013
- const { query, variables } = req.body;
6014
- const { operationName } = parseQuery(query, operationType);
6015
- return {
6016
- operationType,
6017
- operationName,
6018
- variables,
6019
- };
6020
- }
6021
- default:
6057
+ function graphQLRequestHandler(expectedOperationType, expectedOperationName, mask, resolver) {
6058
+ return {
6059
+ resolver,
6060
+ parse(req) {
6061
+ var _a;
6062
+ // According to the GraphQL specification, a GraphQL request can be issued
6063
+ // using both "GET" and "POST" methods.
6064
+ switch (req.method) {
6065
+ case 'GET': {
6066
+ const query = req.url.searchParams.get('query');
6067
+ const variablesString = req.url.searchParams.get('variables') || '';
6068
+ if (!query) {
6022
6069
  return null;
6070
+ }
6071
+ const variables = variablesString
6072
+ ? jsonParse(variablesString)
6073
+ : {};
6074
+ const { operationType, operationName } = parseQuery(query, expectedOperationType);
6075
+ return {
6076
+ operationType,
6077
+ operationName,
6078
+ variables,
6079
+ };
6023
6080
  }
6024
- },
6025
- getPublicRequest(req, parsed) {
6026
- return Object.assign(Object.assign({}, req), { variables: parsed.variables || {} });
6027
- },
6028
- predicate(req, parsed) {
6029
- if (!parsed || !parsed.operationName) {
6030
- return false;
6081
+ case 'POST': {
6082
+ if (!((_a = req.body) === null || _a === void 0 ? void 0 : _a.query)) {
6083
+ return null;
6084
+ }
6085
+ const { query, variables } = req.body;
6086
+ const { operationType, operationName } = parseQuery(query, expectedOperationType);
6087
+ return {
6088
+ operationType,
6089
+ operationName,
6090
+ variables,
6091
+ };
6031
6092
  }
6032
- // Match the request URL against a given mask,
6033
- // in case of an endpoint-specific request handler.
6034
- const hasMatchingMask = matchRequestUrl(req.url, mask);
6035
- const isMatchingOperation = expectedOperation instanceof RegExp
6036
- ? expectedOperation.test(parsed.operationName)
6037
- : expectedOperation === parsed.operationName;
6038
- return isMatchingOperation && hasMatchingMask.matches;
6039
- },
6040
- defineContext() {
6041
- return graphqlContext;
6042
- },
6043
- log(req, res, handler, parsed) {
6044
- const { operationName } = parsed;
6045
- const loggedRequest = prepareRequest(req);
6046
- const loggedResponse = prepareResponse(res);
6047
- console.groupCollapsed('[MSW] %s %s (%c%s%c)', getTimestamp(), operationName, `color:${getStatusCodeColor(res.status)}`, res.status, 'color:inherit');
6048
- console.log('Request:', loggedRequest);
6049
- console.log('Handler:', {
6050
- operationType,
6051
- operationName: expectedOperation,
6052
- predicate: handler.predicate,
6053
- });
6054
- console.log('Response:', loggedResponse);
6055
- console.groupEnd();
6056
- },
6057
- };
6093
+ default:
6094
+ return null;
6095
+ }
6096
+ },
6097
+ getPublicRequest(req, parsed) {
6098
+ return Object.assign(Object.assign({}, req), { variables: parsed.variables || {} });
6099
+ },
6100
+ predicate(req, parsed) {
6101
+ if (!parsed || !parsed.operationName) {
6102
+ return false;
6103
+ }
6104
+ // Match the request URL against a given mask,
6105
+ // in case of an endpoint-specific request handler.
6106
+ const hasMatchingMask = matchRequestUrl(req.url, mask);
6107
+ const isMatchingOperation = expectedOperationName instanceof RegExp
6108
+ ? expectedOperationName.test(parsed.operationName)
6109
+ : expectedOperationName === parsed.operationName;
6110
+ return hasMatchingMask.matches && isMatchingOperation;
6111
+ },
6112
+ defineContext() {
6113
+ return graphqlContext;
6114
+ },
6115
+ log(req, res, handler, parsed) {
6116
+ const { operationType, operationName } = parsed;
6117
+ const loggedRequest = prepareRequest(req);
6118
+ const loggedResponse = prepareResponse(res);
6119
+ console.groupCollapsed('[MSW] %s %s (%c%s%c)', getTimestamp(), operationName, `color:${getStatusCodeColor(res.status)}`, res.status, 'color:inherit');
6120
+ console.log('Request:', loggedRequest);
6121
+ console.log('Handler:', {
6122
+ operationType,
6123
+ operationName: expectedOperationName,
6124
+ predicate: handler.predicate,
6125
+ });
6126
+ console.log('Response:', loggedResponse);
6127
+ console.groupEnd();
6128
+ },
6129
+ };
6130
+ }
6131
+ const createGraphQLScopedHandler = (expectedOperationType, mask) => {
6132
+ return (expectedOperationName, resolver) => {
6133
+ return graphQLRequestHandler(expectedOperationType, expectedOperationName, mask, resolver);
6134
+ };
6135
+ };
6136
+ const createGraphQLOperationHandler = (mask) => {
6137
+ return (resolver) => {
6138
+ return graphQLRequestHandler('all', new RegExp('.*'), mask, resolver);
6058
6139
  };
6059
6140
  };
6060
6141
  const graphqlStandardHandlers = {
6061
- query: createGraphQLHandler('query', '*'),
6062
- mutation: createGraphQLHandler('mutation', '*'),
6142
+ operation: createGraphQLOperationHandler('*'),
6143
+ query: createGraphQLScopedHandler('query', '*'),
6144
+ mutation: createGraphQLScopedHandler('mutation', '*'),
6063
6145
  };
6064
6146
  function createGraphQLLink(uri) {
6065
6147
  return {
6066
- query: createGraphQLHandler('query', uri),
6067
- mutation: createGraphQLHandler('mutation', uri),
6148
+ operation: createGraphQLOperationHandler(uri),
6149
+ query: createGraphQLScopedHandler('query', uri),
6150
+ mutation: createGraphQLScopedHandler('mutation', uri),
6068
6151
  };
6069
6152
  }
6070
6153
  const graphql = Object.assign(Object.assign({}, graphqlStandardHandlers), { link: createGraphQLLink });