msw 0.33.2 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/lib/esm/RequestHandler-deps.js +447 -82
  2. package/lib/esm/errors-deps.js +15 -1
  3. package/lib/esm/fetch-deps.js +9 -5
  4. package/lib/esm/graphql-deps.js +15 -10
  5. package/lib/esm/graphql.js +1 -0
  6. package/lib/esm/index-deps.js +2 -1
  7. package/lib/esm/index.js +90 -3880
  8. package/lib/esm/index2.js +1 -1
  9. package/lib/esm/mockServiceWorker.js +21 -12
  10. package/lib/esm/rest-deps.js +8 -15
  11. package/lib/esm/rest.js +1 -0
  12. package/lib/iife/index.js +3 -3
  13. package/lib/iife/mockServiceWorker.js +21 -12
  14. package/lib/types/context/data.d.ts +2 -3
  15. package/lib/types/context/extensions.d.ts +8 -0
  16. package/lib/types/context/index.d.ts +1 -0
  17. package/lib/types/graphql.d.ts +2 -1
  18. package/lib/types/handlers/GraphQLHandler.d.ts +5 -4
  19. package/lib/types/handlers/RequestHandler.d.ts +1 -1
  20. package/lib/types/handlers/RestHandler.d.ts +8 -10
  21. package/lib/types/index.d.ts +17 -7
  22. package/lib/types/node/glossary.d.ts +4 -14
  23. package/lib/types/node/index.d.ts +1 -1
  24. package/lib/types/rest.d.ts +10 -9
  25. package/lib/types/setupWorker/glossary.d.ts +16 -26
  26. package/lib/types/setupWorker/start/utils/prepareStartHandler.d.ts +3 -3
  27. package/lib/types/sharedOptions.d.ts +12 -1
  28. package/lib/types/typeUtils.d.ts +5 -3
  29. package/lib/types/utils/handleRequest.d.ts +4 -4
  30. package/lib/types/utils/internal/getCallFrame.d.ts +1 -1
  31. package/lib/types/utils/internal/jsonParse.d.ts +2 -2
  32. package/lib/types/utils/internal/pipeEvents.d.ts +6 -0
  33. package/lib/types/utils/logging/prepareResponse.d.ts +1 -1
  34. package/lib/types/utils/matching/matchRequestUrl.d.ts +12 -2
  35. package/lib/types/utils/matching/normalizePath.d.ts +1 -1
  36. package/lib/types/utils/request/parseBody.d.ts +2 -2
  37. package/lib/types/utils/request/parseWorkerRequest.d.ts +2 -2
  38. package/lib/types/utils/worker/createFallbackRequestListener.d.ts +2 -1
  39. package/lib/types/utils/worker/createRequestListener.d.ts +2 -1
  40. package/lib/umd/index.js +1131 -249
  41. package/lib/umd/mockServiceWorker.js +21 -12
  42. package/native/lib/index.js +551 -508
  43. package/node/lib/index.js +553 -510
  44. package/package.json +19 -19
@@ -1,4 +1,5 @@
1
1
  import { c as commonjsGlobal, l as lib$1, j as jsonParse, s as status, b as set, e as delay, f as fetch } from './fetch-deps.js';
2
+ import { getCleanUrl } from '@mswjs/interceptors/lib/utils/getCleanUrl';
2
3
 
3
4
  /*! *****************************************************************************
4
5
  Copyright (c) Microsoft Corporation.
@@ -41,6 +42,65 @@ var lib = {};
41
42
 
42
43
  var invariant$1 = {};
43
44
 
45
+ var format$1 = {};
46
+
47
+ Object.defineProperty(format$1, "__esModule", { value: true });
48
+ format$1.format = void 0;
49
+ var POSITIONALS_EXP = /(%?)(%([sdjo]))/g;
50
+ function serializePositional(positional, flag) {
51
+ switch (flag) {
52
+ // Strings.
53
+ case 's':
54
+ return positional;
55
+ // Digits.
56
+ case 'd':
57
+ case 'i':
58
+ return Number(positional);
59
+ // JSON.
60
+ case 'j':
61
+ return JSON.stringify(positional);
62
+ // Objects.
63
+ case 'o': {
64
+ // Preserve stings to prevent extra quotes around them.
65
+ if (typeof positional === 'string') {
66
+ return positional;
67
+ }
68
+ var json = JSON.stringify(positional);
69
+ // If the positional isn't serializable, return it as-is.
70
+ if (json === '{}' || json === '[]' || /^\[object .+?\]$/.test(json)) {
71
+ return positional;
72
+ }
73
+ return json;
74
+ }
75
+ }
76
+ }
77
+ function format(message) {
78
+ var positionals = [];
79
+ for (var _i = 1; _i < arguments.length; _i++) {
80
+ positionals[_i - 1] = arguments[_i];
81
+ }
82
+ if (positionals.length === 0) {
83
+ return message;
84
+ }
85
+ var positionalIndex = 0;
86
+ var formattedMessage = message.replace(POSITIONALS_EXP, function (match, isEscaped, _, flag) {
87
+ var positional = positionals[positionalIndex];
88
+ var value = serializePositional(positional, flag);
89
+ if (!isEscaped) {
90
+ positionalIndex++;
91
+ return value;
92
+ }
93
+ return match;
94
+ });
95
+ // Append unresolved positionals to string as-is.
96
+ if (positionalIndex < positionals.length) {
97
+ formattedMessage += " " + positionals.slice(positionalIndex).join(' ');
98
+ }
99
+ formattedMessage = formattedMessage.replace(/%{2,2}/g, '%');
100
+ return formattedMessage;
101
+ }
102
+ format$1.format = format;
103
+
44
104
  var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () {
45
105
  var extendStatics = function (d, b) {
46
106
  extendStatics = Object.setPrototypeOf ||
@@ -62,21 +122,9 @@ var __spreadArray = (commonjsGlobal && commonjsGlobal.__spreadArray) || function
62
122
  return to;
63
123
  };
64
124
  Object.defineProperty(invariant$1, "__esModule", { value: true });
65
- invariant$1.invariant = invariant$1.InvariantError = invariant$1.interpolate = void 0;
125
+ invariant$1.invariant = invariant$1.InvariantError = void 0;
126
+ var format_1 = format$1;
66
127
  var STACK_FRAMES_TO_IGNORE = 2;
67
- function interpolate(message) {
68
- var positionals = [];
69
- for (var _i = 1; _i < arguments.length; _i++) {
70
- positionals[_i - 1] = arguments[_i];
71
- }
72
- var index = 0;
73
- return message.replace(/%[s|d|o]/g, function (match) {
74
- var _a;
75
- var value = (_a = positionals[index++]) !== null && _a !== void 0 ? _a : match;
76
- return typeof value === 'object' ? JSON.stringify(value) : value;
77
- });
78
- }
79
- invariant$1.interpolate = interpolate;
80
128
  var InvariantError = /** @class */ (function (_super) {
81
129
  __extends(InvariantError, _super);
82
130
  function InvariantError(message) {
@@ -86,7 +134,7 @@ var InvariantError = /** @class */ (function (_super) {
86
134
  }
87
135
  var _this = _super.call(this, message) || this;
88
136
  _this.name = 'Invariant Violation';
89
- _this.message = interpolate.apply(void 0, __spreadArray([message], positionals));
137
+ _this.message = format_1.format.apply(void 0, __spreadArray([message], positionals));
90
138
  if (_this.stack) {
91
139
  var prevStack = _this.stack;
92
140
  _this.stack = prevStack
@@ -123,6 +171,7 @@ var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m
123
171
  };
124
172
  Object.defineProperty(exports, "__esModule", { value: true });
125
173
  __exportStar(invariant$1, exports);
174
+ __exportStar(format$1, exports);
126
175
  }(lib));
127
176
 
128
177
  const LIBRARY_PREFIX = '[MSW]';
@@ -130,7 +179,7 @@ const LIBRARY_PREFIX = '[MSW]';
130
179
  * Formats a given message by appending the library's prefix string.
131
180
  */
132
181
  function formatMessage(message, ...positionals) {
133
- const interpolatedMessage = lib.interpolate(message, ...positionals);
182
+ const interpolatedMessage = lib.format(message, ...positionals);
134
183
  return `${LIBRARY_PREFIX} ${interpolatedMessage}`;
135
184
  }
136
185
  /**
@@ -231,25 +280,25 @@ function parseMultipartData(data, headers) {
231
280
  }
232
281
 
233
282
  /**
234
- * Parses a given request/response body based on the `Content-Type` header.
283
+ * Parses a given request/response body based on the "Content-Type" header.
235
284
  */
236
285
  function parseBody(body, headers) {
237
286
  // Return whatever falsey body value is given.
238
287
  if (!body) {
239
288
  return body;
240
289
  }
241
- const contentType = headers === null || headers === void 0 ? void 0 : headers.get('content-type');
290
+ const contentType = (headers === null || headers === void 0 ? void 0 : headers.get('content-type')) || '';
242
291
  // If the body has a Multipart Content-Type
243
292
  // parse it into an object.
244
- const hasMultipartContent = contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('multipart/form-data');
293
+ const hasMultipartContent = contentType.startsWith('multipart/form-data');
245
294
  if (hasMultipartContent && typeof body !== 'object') {
246
- return parseMultipartData(body, headers) || body;
295
+ return parseMultipartData(body.toString(), headers) || body;
247
296
  }
248
297
  // If the intercepted request's body has a JSON Content-Type
249
298
  // parse it into an object.
250
- const hasJsonContent = contentType === null || contentType === void 0 ? void 0 : contentType.includes('json');
299
+ const hasJsonContent = contentType.includes('json');
251
300
  if (hasJsonContent && typeof body !== 'object') {
252
- return jsonParse(body) || body;
301
+ return jsonParse(body.toString()) || body;
253
302
  }
254
303
  // Otherwise leave as-is.
255
304
  return body;
@@ -313,57 +362,339 @@ function prepareResponse(res) {
313
362
  body: parseBody(res.body, responseHeaders) });
314
363
  }
315
364
 
316
- /**
317
- * Converts a string path to a Regular Expression.
318
- * Transforms path parameters into named RegExp groups.
319
- */
320
- const pathToRegExp = (path) => {
321
- const pattern = path
322
- // Escape literal dots
323
- .replace(/\./g, '\\.')
324
- // Escape literal slashes
325
- .replace(/\//g, '/')
326
- // Escape literal question marks
327
- .replace(/\?/g, '\\?')
328
- // Ignore trailing slashes
329
- .replace(/\/+$/, '')
330
- // Replace wildcard with any zero-to-any character sequence
331
- .replace(/\*+/g, '.*')
332
- // Replace parameters with named capturing groups
333
- .replace(/:([^\d|^\/][a-zA-Z0-9_]*(?=(?:\/|\\.)|$))/g, (_, paramName) => `(?<${paramName}>[^\/]+?)`)
334
- // Allow optional trailing slash
335
- .concat('(\\/|$)');
336
- return new RegExp(pattern, 'gi');
337
- };
338
-
339
- /**
340
- * Matches a given url against a path.
341
- */
342
- const match = (path, url) => {
343
- const expression = path instanceof RegExp ? path : pathToRegExp(path);
344
- const match = expression.exec(url) || false;
345
- // Matches in strict mode: match string should equal to input (url)
346
- // Otherwise loose matches will be considered truthy:
347
- // match('/messages/:id', '/messages/123/users') // true
348
- const matches = path instanceof RegExp ? !!match : !!match && match[0] === match.input;
349
- return {
350
- matches,
351
- params: match && matches ? match.groups || null : null,
352
- };
353
- };
354
-
355
- var getCleanUrl$1 = {};
356
-
357
- Object.defineProperty(getCleanUrl$1, "__esModule", { value: true });
358
- var getCleanUrl_2 = getCleanUrl$1.getCleanUrl = void 0;
359
365
  /**
360
- * Removes query parameters and hashes from a given URL.
366
+ * Tokenize input string.
361
367
  */
362
- function getCleanUrl(url, isAbsolute) {
363
- if (isAbsolute === void 0) { isAbsolute = true; }
364
- return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('');
368
+ function lexer(str) {
369
+ var tokens = [];
370
+ var i = 0;
371
+ while (i < str.length) {
372
+ var char = str[i];
373
+ if (char === "*" || char === "+" || char === "?") {
374
+ tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
375
+ continue;
376
+ }
377
+ if (char === "\\") {
378
+ tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
379
+ continue;
380
+ }
381
+ if (char === "{") {
382
+ tokens.push({ type: "OPEN", index: i, value: str[i++] });
383
+ continue;
384
+ }
385
+ if (char === "}") {
386
+ tokens.push({ type: "CLOSE", index: i, value: str[i++] });
387
+ continue;
388
+ }
389
+ if (char === ":") {
390
+ var name = "";
391
+ var j = i + 1;
392
+ while (j < str.length) {
393
+ var code = str.charCodeAt(j);
394
+ if (
395
+ // `0-9`
396
+ (code >= 48 && code <= 57) ||
397
+ // `A-Z`
398
+ (code >= 65 && code <= 90) ||
399
+ // `a-z`
400
+ (code >= 97 && code <= 122) ||
401
+ // `_`
402
+ code === 95) {
403
+ name += str[j++];
404
+ continue;
405
+ }
406
+ break;
407
+ }
408
+ if (!name)
409
+ throw new TypeError("Missing parameter name at " + i);
410
+ tokens.push({ type: "NAME", index: i, value: name });
411
+ i = j;
412
+ continue;
413
+ }
414
+ if (char === "(") {
415
+ var count = 1;
416
+ var pattern = "";
417
+ var j = i + 1;
418
+ if (str[j] === "?") {
419
+ throw new TypeError("Pattern cannot start with \"?\" at " + j);
420
+ }
421
+ while (j < str.length) {
422
+ if (str[j] === "\\") {
423
+ pattern += str[j++] + str[j++];
424
+ continue;
425
+ }
426
+ if (str[j] === ")") {
427
+ count--;
428
+ if (count === 0) {
429
+ j++;
430
+ break;
431
+ }
432
+ }
433
+ else if (str[j] === "(") {
434
+ count++;
435
+ if (str[j + 1] !== "?") {
436
+ throw new TypeError("Capturing groups are not allowed at " + j);
437
+ }
438
+ }
439
+ pattern += str[j++];
440
+ }
441
+ if (count)
442
+ throw new TypeError("Unbalanced pattern at " + i);
443
+ if (!pattern)
444
+ throw new TypeError("Missing pattern at " + i);
445
+ tokens.push({ type: "PATTERN", index: i, value: pattern });
446
+ i = j;
447
+ continue;
448
+ }
449
+ tokens.push({ type: "CHAR", index: i, value: str[i++] });
450
+ }
451
+ tokens.push({ type: "END", index: i, value: "" });
452
+ return tokens;
453
+ }
454
+ /**
455
+ * Parse a string for the raw tokens.
456
+ */
457
+ function parse(str, options) {
458
+ if (options === void 0) { options = {}; }
459
+ var tokens = lexer(str);
460
+ var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a;
461
+ var defaultPattern = "[^" + escapeString(options.delimiter || "/#?") + "]+?";
462
+ var result = [];
463
+ var key = 0;
464
+ var i = 0;
465
+ var path = "";
466
+ var tryConsume = function (type) {
467
+ if (i < tokens.length && tokens[i].type === type)
468
+ return tokens[i++].value;
469
+ };
470
+ var mustConsume = function (type) {
471
+ var value = tryConsume(type);
472
+ if (value !== undefined)
473
+ return value;
474
+ var _a = tokens[i], nextType = _a.type, index = _a.index;
475
+ throw new TypeError("Unexpected " + nextType + " at " + index + ", expected " + type);
476
+ };
477
+ var consumeText = function () {
478
+ var result = "";
479
+ var value;
480
+ // tslint:disable-next-line
481
+ while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
482
+ result += value;
483
+ }
484
+ return result;
485
+ };
486
+ while (i < tokens.length) {
487
+ var char = tryConsume("CHAR");
488
+ var name = tryConsume("NAME");
489
+ var pattern = tryConsume("PATTERN");
490
+ if (name || pattern) {
491
+ var prefix = char || "";
492
+ if (prefixes.indexOf(prefix) === -1) {
493
+ path += prefix;
494
+ prefix = "";
495
+ }
496
+ if (path) {
497
+ result.push(path);
498
+ path = "";
499
+ }
500
+ result.push({
501
+ name: name || key++,
502
+ prefix: prefix,
503
+ suffix: "",
504
+ pattern: pattern || defaultPattern,
505
+ modifier: tryConsume("MODIFIER") || ""
506
+ });
507
+ continue;
508
+ }
509
+ var value = char || tryConsume("ESCAPED_CHAR");
510
+ if (value) {
511
+ path += value;
512
+ continue;
513
+ }
514
+ if (path) {
515
+ result.push(path);
516
+ path = "";
517
+ }
518
+ var open = tryConsume("OPEN");
519
+ if (open) {
520
+ var prefix = consumeText();
521
+ var name_1 = tryConsume("NAME") || "";
522
+ var pattern_1 = tryConsume("PATTERN") || "";
523
+ var suffix = consumeText();
524
+ mustConsume("CLOSE");
525
+ result.push({
526
+ name: name_1 || (pattern_1 ? key++ : ""),
527
+ pattern: name_1 && !pattern_1 ? defaultPattern : pattern_1,
528
+ prefix: prefix,
529
+ suffix: suffix,
530
+ modifier: tryConsume("MODIFIER") || ""
531
+ });
532
+ continue;
533
+ }
534
+ mustConsume("END");
535
+ }
536
+ return result;
537
+ }
538
+ /**
539
+ * Create path match function from `path-to-regexp` spec.
540
+ */
541
+ function match(str, options) {
542
+ var keys = [];
543
+ var re = pathToRegexp(str, keys, options);
544
+ return regexpToFunction(re, keys, options);
545
+ }
546
+ /**
547
+ * Create a path match function from `path-to-regexp` output.
548
+ */
549
+ function regexpToFunction(re, keys, options) {
550
+ if (options === void 0) { options = {}; }
551
+ var _a = options.decode, decode = _a === void 0 ? function (x) { return x; } : _a;
552
+ return function (pathname) {
553
+ var m = re.exec(pathname);
554
+ if (!m)
555
+ return false;
556
+ var path = m[0], index = m.index;
557
+ var params = Object.create(null);
558
+ var _loop_1 = function (i) {
559
+ // tslint:disable-next-line
560
+ if (m[i] === undefined)
561
+ return "continue";
562
+ var key = keys[i - 1];
563
+ if (key.modifier === "*" || key.modifier === "+") {
564
+ params[key.name] = m[i].split(key.prefix + key.suffix).map(function (value) {
565
+ return decode(value, key);
566
+ });
567
+ }
568
+ else {
569
+ params[key.name] = decode(m[i], key);
570
+ }
571
+ };
572
+ for (var i = 1; i < m.length; i++) {
573
+ _loop_1(i);
574
+ }
575
+ return { path: path, index: index, params: params };
576
+ };
577
+ }
578
+ /**
579
+ * Escape a regular expression string.
580
+ */
581
+ function escapeString(str) {
582
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
583
+ }
584
+ /**
585
+ * Get the flags for a regexp from the options.
586
+ */
587
+ function flags(options) {
588
+ return options && options.sensitive ? "" : "i";
589
+ }
590
+ /**
591
+ * Pull out keys from a regexp.
592
+ */
593
+ function regexpToRegexp(path, keys) {
594
+ if (!keys)
595
+ return path;
596
+ var groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
597
+ var index = 0;
598
+ var execResult = groupsRegex.exec(path.source);
599
+ while (execResult) {
600
+ keys.push({
601
+ // Use parenthesized substring match if available, index otherwise
602
+ name: execResult[1] || index++,
603
+ prefix: "",
604
+ suffix: "",
605
+ modifier: "",
606
+ pattern: ""
607
+ });
608
+ execResult = groupsRegex.exec(path.source);
609
+ }
610
+ return path;
611
+ }
612
+ /**
613
+ * Transform an array into a regexp.
614
+ */
615
+ function arrayToRegexp(paths, keys, options) {
616
+ var parts = paths.map(function (path) { return pathToRegexp(path, keys, options).source; });
617
+ return new RegExp("(?:" + parts.join("|") + ")", flags(options));
618
+ }
619
+ /**
620
+ * Create a path regexp from string input.
621
+ */
622
+ function stringToRegexp(path, keys, options) {
623
+ return tokensToRegexp(parse(path, options), keys, options);
624
+ }
625
+ /**
626
+ * Expose a function for taking tokens and returning a RegExp.
627
+ */
628
+ function tokensToRegexp(tokens, keys, options) {
629
+ if (options === void 0) { options = {}; }
630
+ var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d;
631
+ var endsWith = "[" + escapeString(options.endsWith || "") + "]|$";
632
+ var delimiter = "[" + escapeString(options.delimiter || "/#?") + "]";
633
+ var route = start ? "^" : "";
634
+ // Iterate over the tokens and create our regexp string.
635
+ for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
636
+ var token = tokens_1[_i];
637
+ if (typeof token === "string") {
638
+ route += escapeString(encode(token));
639
+ }
640
+ else {
641
+ var prefix = escapeString(encode(token.prefix));
642
+ var suffix = escapeString(encode(token.suffix));
643
+ if (token.pattern) {
644
+ if (keys)
645
+ keys.push(token);
646
+ if (prefix || suffix) {
647
+ if (token.modifier === "+" || token.modifier === "*") {
648
+ var mod = token.modifier === "*" ? "?" : "";
649
+ route += "(?:" + prefix + "((?:" + token.pattern + ")(?:" + suffix + prefix + "(?:" + token.pattern + "))*)" + suffix + ")" + mod;
650
+ }
651
+ else {
652
+ route += "(?:" + prefix + "(" + token.pattern + ")" + suffix + ")" + token.modifier;
653
+ }
654
+ }
655
+ else {
656
+ route += "(" + token.pattern + ")" + token.modifier;
657
+ }
658
+ }
659
+ else {
660
+ route += "(?:" + prefix + suffix + ")" + token.modifier;
661
+ }
662
+ }
663
+ }
664
+ if (end) {
665
+ if (!strict)
666
+ route += delimiter + "?";
667
+ route += !options.endsWith ? "$" : "(?=" + endsWith + ")";
668
+ }
669
+ else {
670
+ var endToken = tokens[tokens.length - 1];
671
+ var isEndDelimited = typeof endToken === "string"
672
+ ? delimiter.indexOf(endToken[endToken.length - 1]) > -1
673
+ : // tslint:disable-next-line
674
+ endToken === undefined;
675
+ if (!strict) {
676
+ route += "(?:" + delimiter + "(?=" + endsWith + "))?";
677
+ }
678
+ if (!isEndDelimited) {
679
+ route += "(?=" + delimiter + "|" + endsWith + ")";
680
+ }
681
+ }
682
+ return new RegExp(route, flags(options));
683
+ }
684
+ /**
685
+ * Normalize the given path string, returning a regular expression.
686
+ *
687
+ * An empty array can be passed in for the keys, which will hold the
688
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
689
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
690
+ */
691
+ function pathToRegexp(path, keys, options) {
692
+ if (path instanceof RegExp)
693
+ return regexpToRegexp(path, keys);
694
+ if (Array.isArray(path))
695
+ return arrayToRegexp(path, keys, options);
696
+ return stringToRegexp(path, keys, options);
365
697
  }
366
- getCleanUrl_2 = getCleanUrl$1.getCleanUrl = getCleanUrl;
367
698
 
368
699
  const REDUNDANT_CHARACTERS_EXP = /[\?|#].*$/g;
369
700
  function getSearchParams(path) {
@@ -385,9 +716,12 @@ function getAbsoluteUrl(path, baseUrl) {
385
716
  return path;
386
717
  }
387
718
  // Resolve a relative request URL against a given custom "baseUrl"
388
- // or the current location (in the case of browser/browser-like environments).
389
- const origin = baseUrl || (typeof location !== 'undefined' && location.origin);
390
- return origin ? new URL(path, origin).href : path;
719
+ // or the document baseURI (in the case of browser/browser-like environments).
720
+ const origin = baseUrl || (typeof document !== 'undefined' && document.baseURI);
721
+ return origin
722
+ ? // Encode and decode the path to preserve escaped characters.
723
+ decodeURI(new URL(encodeURI(path), origin).href)
724
+ : path;
391
725
  }
392
726
 
393
727
  /**
@@ -406,12 +740,40 @@ function normalizePath(path, baseUrl) {
406
740
  return cleanUrl(maybeAbsoluteUrl);
407
741
  }
408
742
 
743
+ /**
744
+ * Coerce a path supported by MSW into a path
745
+ * supported by "path-to-regexp".
746
+ */
747
+ function coercePath(path) {
748
+ return (path
749
+ /**
750
+ * Escape the protocol so that "path-to-regexp" could match
751
+ * absolute URL.
752
+ * @see https://github.com/pillarjs/path-to-regexp/issues/259
753
+ */
754
+ .replace(/^([^\/]+)(:)(?=\/\/)/g, '$1\\$2')
755
+ /**
756
+ * Replace wildcards ("*") with unnamed capturing groups
757
+ * because "path-to-regexp" doesn't support wildcards.
758
+ * Ignore path parameter' modifiers (i.e. ":name*").
759
+ */
760
+ .replace(/(?<!(^|\/|\*+):[\w]+)(\*{1,2})/g, '(.*)'));
761
+ }
409
762
  /**
410
763
  * Returns the result of matching given request URL against a mask.
411
764
  */
412
765
  function matchRequestUrl(url, path, baseUrl) {
413
766
  const normalizedPath = normalizePath(path, baseUrl);
414
- return match(normalizedPath, getCleanUrl_2(url));
767
+ const cleanPath = typeof normalizedPath === 'string'
768
+ ? coercePath(normalizedPath)
769
+ : normalizedPath;
770
+ const cleanUrl = getCleanUrl(url);
771
+ const result = match(cleanPath, { decode: decodeURIComponent })(cleanUrl);
772
+ const params = (result && result.params) || {};
773
+ return {
774
+ matches: result !== false,
775
+ params,
776
+ };
415
777
  }
416
778
 
417
779
  /**
@@ -460,18 +822,21 @@ const response = Object.assign(createResponseComposition(), {
460
822
  },
461
823
  });
462
824
 
825
+ const BUILD_FRAME = /(node_modules)?[\/\\]lib[\/\\](umd|esm|iief|cjs)[\/\\]|^[^\/\\]*$/;
463
826
  /**
464
827
  * Return the stack trace frame of a function's invocation.
465
828
  */
466
- function getCallFrame() {
829
+ function getCallFrame(error) {
467
830
  // In <IE11, new Error may return an undefined stack
468
- const stack = (new Error().stack || '');
469
- const frames = stack.split('\n');
831
+ const stack = error.stack;
832
+ if (!stack) {
833
+ return;
834
+ }
835
+ const frames = stack.split('\n').slice(1);
470
836
  // Get the first frame that doesn't reference the library's internal trace.
471
837
  // Assume that frame is the invocation frame.
472
- const ignoreFrameRegExp = /(node_modules)?[\/\\]lib[\/\\](umd|esm|iief|cjs)[\/\\]|^[^\/\\]*$/;
473
- const declarationFrame = frames.slice(1).find((frame) => {
474
- return !ignoreFrameRegExp.test(frame);
838
+ const declarationFrame = frames.find((frame) => {
839
+ return !BUILD_FRAME.test(frame);
475
840
  });
476
841
  if (!declarationFrame) {
477
842
  return;
@@ -504,7 +869,7 @@ class RequestHandler {
504
869
  this.shouldSkip = false;
505
870
  this.ctx = options.ctx || defaultContext;
506
871
  this.resolver = options.resolver;
507
- const callFrame = getCallFrame();
872
+ const callFrame = getCallFrame(new Error());
508
873
  this.info = Object.assign(Object.assign({}, options.info), { callFrame });
509
874
  }
510
875
  /**
@@ -582,4 +947,4 @@ class RequestHandler {
582
947
  }
583
948
  }
584
949
 
585
- export { NetworkError as N, RequestHandler as R, __awaiter as _, getCleanUrl$1 as a, defaultResponse as b, createResponseComposition as c, devUtils as d, defaultContext as e, compose as f, getPublicUrlFromRequest as g, cleanUrl as h, getSearchParams as i, prepareRequest as j, prepareResponse as k, lib as l, matchRequestUrl as m, getStatusCodeColor as n, getTimestamp as o, parseBody as p, __rest as q, response as r };
950
+ export { NetworkError as N, RequestHandler as R, __awaiter as _, defaultResponse as a, defaultContext as b, createResponseComposition as c, devUtils as d, compose as e, cleanUrl as f, getPublicUrlFromRequest as g, getSearchParams as h, prepareRequest as i, prepareResponse as j, getStatusCodeColor as k, getTimestamp as l, matchRequestUrl as m, __rest as n, parseBody as p, response as r };
@@ -41,6 +41,20 @@ const data = (payload) => {
41
41
  };
42
42
  };
43
43
 
44
+ /**
45
+ * Sets the GraphQL extensions on a given response.
46
+ * @example
47
+ * res(ctx.extensions({ tracing: { version: 1 }}))
48
+ * @see {@link https://mswjs.io/docs/api/context/extensions `ctx.extensions()`}
49
+ */
50
+ const extensions = (payload) => {
51
+ return (res) => {
52
+ const prevBody = jsonParse(res.body) || {};
53
+ const nextBody = mergeRight(prevBody, { extensions: payload });
54
+ return json(nextBody)(res);
55
+ };
56
+ };
57
+
44
58
  /**
45
59
  * Sets a given list of GraphQL errors on the mocked response.
46
60
  * @example res(ctx.errors([{ message: 'Unauthorized' }]))
@@ -57,4 +71,4 @@ const errors = (errorsList) => {
57
71
  };
58
72
  };
59
73
 
60
- export { data as d, errors as e, mergeRight as m };
74
+ export { errors as a, data as d, extensions as e, mergeRight as m };
@@ -851,12 +851,12 @@ const cookie = (name, value, options) => {
851
851
  };
852
852
 
853
853
  /**
854
- * Parses a given string into a JSON.
854
+ * Parses a given value into a JSON.
855
855
  * Does not throw an exception on an invalid JSON string.
856
856
  */
857
- function jsonParse(str) {
857
+ function jsonParse(value) {
858
858
  try {
859
- return JSON.parse(str);
859
+ return JSON.parse(value);
860
860
  }
861
861
  catch (error) {
862
862
  return undefined;
@@ -974,8 +974,12 @@ const createFetchRequestParameters = (input) => {
974
974
  if (['GET', 'HEAD'].includes(method)) {
975
975
  return requestParameters;
976
976
  }
977
- requestParameters.body =
978
- typeof body === 'object' ? JSON.stringify(body) : body;
977
+ if (typeof body === 'object' || typeof body === 'number') {
978
+ requestParameters.body = JSON.stringify(body);
979
+ }
980
+ else {
981
+ requestParameters.body = body;
982
+ }
979
983
  return requestParameters;
980
984
  };
981
985
  /**