msw 2.11.1 → 2.11.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 (72) hide show
  1. package/lib/browser/index.d.mts +0 -3
  2. package/lib/browser/index.d.ts +0 -3
  3. package/lib/browser/index.js +536 -318
  4. package/lib/browser/index.js.map +1 -1
  5. package/lib/browser/index.mjs +536 -318
  6. package/lib/browser/index.mjs.map +1 -1
  7. package/lib/core/handlers/GraphQLHandler.js.map +1 -1
  8. package/lib/core/handlers/GraphQLHandler.mjs.map +1 -1
  9. package/lib/core/handlers/HttpHandler.js.map +1 -1
  10. package/lib/core/handlers/HttpHandler.mjs.map +1 -1
  11. package/lib/core/utils/handleRequest.js +8 -8
  12. package/lib/core/utils/handleRequest.js.map +1 -1
  13. package/lib/core/utils/handleRequest.mjs +8 -8
  14. package/lib/core/utils/handleRequest.mjs.map +1 -1
  15. package/lib/core/utils/internal/devUtils.js.map +1 -1
  16. package/lib/core/utils/internal/devUtils.mjs.map +1 -1
  17. package/lib/core/utils/internal/getCallFrame.js +2 -2
  18. package/lib/core/utils/internal/getCallFrame.js.map +1 -1
  19. package/lib/core/utils/internal/getCallFrame.mjs +2 -2
  20. package/lib/core/utils/internal/getCallFrame.mjs.map +1 -1
  21. package/lib/core/utils/internal/parseGraphQLRequest.js +1 -0
  22. package/lib/core/utils/internal/parseGraphQLRequest.js.map +1 -1
  23. package/lib/core/utils/internal/parseGraphQLRequest.mjs +1 -0
  24. package/lib/core/utils/internal/parseGraphQLRequest.mjs.map +1 -1
  25. package/lib/core/utils/matching/matchRequestUrl.js +1 -1
  26. package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
  27. package/lib/core/utils/matching/matchRequestUrl.mjs +1 -1
  28. package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
  29. package/lib/core/utils/url/cleanUrl.js +1 -1
  30. package/lib/core/utils/url/cleanUrl.js.map +1 -1
  31. package/lib/core/utils/url/cleanUrl.mjs +1 -1
  32. package/lib/core/utils/url/cleanUrl.mjs.map +1 -1
  33. package/lib/core/utils/url/isAbsoluteUrl.js +1 -1
  34. package/lib/core/utils/url/isAbsoluteUrl.js.map +1 -1
  35. package/lib/core/utils/url/isAbsoluteUrl.mjs +1 -1
  36. package/lib/core/utils/url/isAbsoluteUrl.mjs.map +1 -1
  37. package/lib/core/ws/WebSocketIndexedDBClientStore.js.map +1 -1
  38. package/lib/core/ws/WebSocketIndexedDBClientStore.mjs.map +1 -1
  39. package/lib/core/ws/utils/attachWebSocketLogger.js.map +1 -1
  40. package/lib/core/ws/utils/attachWebSocketLogger.mjs.map +1 -1
  41. package/lib/iife/index.js +2536 -2314
  42. package/lib/iife/index.js.map +1 -1
  43. package/lib/mockServiceWorker.js +16 -12
  44. package/package.json +22 -15
  45. package/src/browser/setupWorker/glossary.ts +9 -114
  46. package/src/browser/setupWorker/setupWorker.ts +82 -119
  47. package/src/browser/setupWorker/start/createRequestListener.ts +20 -24
  48. package/src/browser/setupWorker/start/createResponseListener.ts +15 -22
  49. package/src/browser/setupWorker/start/createStartHandler.ts +24 -18
  50. package/src/browser/setupWorker/start/utils/enableMocking.ts +18 -21
  51. package/src/browser/setupWorker/start/utils/getWorkerInstance.ts +17 -16
  52. package/src/browser/setupWorker/start/utils/printStartMessage.ts +0 -2
  53. package/src/browser/utils/checkWorkerIntegrity.ts +22 -14
  54. package/src/browser/utils/deferNetworkRequestsUntil.ts +1 -1
  55. package/src/browser/utils/workerChannel.ts +146 -0
  56. package/src/core/handlers/GraphQLHandler.ts +0 -3
  57. package/src/core/handlers/HttpHandler.ts +0 -2
  58. package/src/core/utils/handleRequest.ts +8 -8
  59. package/src/core/utils/internal/devUtils.ts +0 -2
  60. package/src/core/utils/internal/getCallFrame.ts +2 -2
  61. package/src/core/utils/internal/parseGraphQLRequest.ts +1 -0
  62. package/src/core/utils/matching/matchRequestUrl.ts +2 -2
  63. package/src/core/utils/request/onUnhandledRequest.test.ts +1 -1
  64. package/src/core/utils/url/cleanUrl.ts +1 -1
  65. package/src/core/utils/url/isAbsoluteUrl.ts +1 -1
  66. package/src/core/ws/WebSocketIndexedDBClientStore.ts +0 -4
  67. package/src/core/ws/utils/attachWebSocketLogger.ts +0 -14
  68. package/src/mockServiceWorker.js +14 -10
  69. package/src/browser/setupWorker/start/createFallbackStart.ts +0 -21
  70. package/src/browser/setupWorker/start/utils/createMessageChannel.ts +0 -32
  71. package/src/browser/setupWorker/stop/createFallbackStop.ts +0 -11
  72. package/src/browser/setupWorker/stop/createStop.ts +0 -35
@@ -36,7 +36,7 @@ function coercePath(path) {
36
36
  }
37
37
  return parameterName.startsWith(":") ? `${parameterName}${wildcard}` : `${parameterName}${expression}`;
38
38
  }
39
- ).replace(/([^\/])(:)(?=\d+)/, "$1\\$2").replace(/^([^\/]+)(:)(?=\/\/)/, "$1\\$2");
39
+ ).replace(/([^/])(:)(?=\d+)/, "$1\\$2").replace(/^([^/]+)(:)(?=\/\/)/, "$1\\$2");
40
40
  }
41
41
  function matchRequestUrl(url, path, baseUrl) {
42
42
  const normalizedPath = (0, import_normalizePath.normalizePath)(path, baseUrl);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/utils/matching/matchRequestUrl.ts"],"sourcesContent":["import { match } from 'path-to-regexp'\nimport { getCleanUrl } from '@mswjs/interceptors'\nimport { normalizePath } from './normalizePath'\n\nexport type Path = string | RegExp\nexport type PathParams<KeyType extends keyof any = string> = {\n [ParamName in KeyType]?: string | ReadonlyArray<string>\n}\n\nexport interface Match {\n matches: boolean\n params?: PathParams\n}\n\n/**\n * Coerce a path supported by MSW into a path\n * supported by \"path-to-regexp\".\n */\nexport function coercePath(path: string): string {\n return (\n path\n /**\n * Replace wildcards (\"*\") with unnamed capturing groups\n * because \"path-to-regexp\" doesn't support wildcards.\n * Ignore path parameter' modifiers (i.e. \":name*\").\n */\n .replace(\n /([:a-zA-Z_-]*)(\\*{1,2})+/g,\n (_, parameterName: string | undefined, wildcard: string) => {\n const expression = '(.*)'\n\n if (!parameterName) {\n return expression\n }\n\n return parameterName.startsWith(':')\n ? `${parameterName}${wildcard}`\n : `${parameterName}${expression}`\n },\n )\n /**\n * Escape the port so that \"path-to-regexp\" can match\n * absolute URLs including port numbers.\n */\n .replace(/([^\\/])(:)(?=\\d+)/, '$1\\\\$2')\n /**\n * Escape the protocol so that \"path-to-regexp\" could match\n * absolute URL.\n * @see https://github.com/pillarjs/path-to-regexp/issues/259\n */\n .replace(/^([^\\/]+)(:)(?=\\/\\/)/, '$1\\\\$2')\n )\n}\n\n/**\n * Returns the result of matching given request URL against a mask.\n */\nexport function matchRequestUrl(url: URL, path: Path, baseUrl?: string): Match {\n const normalizedPath = normalizePath(path, baseUrl)\n const cleanPath =\n typeof normalizedPath === 'string'\n ? coercePath(normalizedPath)\n : normalizedPath\n\n const cleanUrl = getCleanUrl(url)\n const result = match(cleanPath, { decode: decodeURIComponent })(cleanUrl)\n const params = (result && (result.params as PathParams)) || {}\n\n return {\n matches: result !== false,\n params,\n }\n}\n\nexport function isPath(value: unknown): value is Path {\n return typeof value === 'string' || value instanceof RegExp\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAsB;AACtB,0BAA4B;AAC5B,2BAA8B;AAgBvB,SAAS,WAAW,MAAsB;AAC/C,SACE,KAMG;AAAA,IACC;AAAA,IACA,CAAC,GAAG,eAAmC,aAAqB;AAC1D,YAAM,aAAa;AAEnB,UAAI,CAAC,eAAe;AAClB,eAAO;AAAA,MACT;AAEA,aAAO,cAAc,WAAW,GAAG,IAC/B,GAAG,aAAa,GAAG,QAAQ,KAC3B,GAAG,aAAa,GAAG,UAAU;AAAA,IACnC;AAAA,EACF,EAKC,QAAQ,qBAAqB,QAAQ,EAMrC,QAAQ,wBAAwB,QAAQ;AAE/C;AAKO,SAAS,gBAAgB,KAAU,MAAY,SAAyB;AAC7E,QAAM,qBAAiB,oCAAc,MAAM,OAAO;AAClD,QAAM,YACJ,OAAO,mBAAmB,WACtB,WAAW,cAAc,IACzB;AAEN,QAAM,eAAW,iCAAY,GAAG;AAChC,QAAM,aAAS,6BAAM,WAAW,EAAE,QAAQ,mBAAmB,CAAC,EAAE,QAAQ;AACxE,QAAM,SAAU,UAAW,OAAO,UAA0B,CAAC;AAE7D,SAAO;AAAA,IACL,SAAS,WAAW;AAAA,IACpB;AAAA,EACF;AACF;AAEO,SAAS,OAAO,OAA+B;AACpD,SAAO,OAAO,UAAU,YAAY,iBAAiB;AACvD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/utils/matching/matchRequestUrl.ts"],"sourcesContent":["import { match } from 'path-to-regexp'\nimport { getCleanUrl } from '@mswjs/interceptors'\nimport { normalizePath } from './normalizePath'\n\nexport type Path = string | RegExp\nexport type PathParams<KeyType extends keyof any = string> = {\n [ParamName in KeyType]?: string | ReadonlyArray<string>\n}\n\nexport interface Match {\n matches: boolean\n params?: PathParams\n}\n\n/**\n * Coerce a path supported by MSW into a path\n * supported by \"path-to-regexp\".\n */\nexport function coercePath(path: string): string {\n return (\n path\n /**\n * Replace wildcards (\"*\") with unnamed capturing groups\n * because \"path-to-regexp\" doesn't support wildcards.\n * Ignore path parameter' modifiers (i.e. \":name*\").\n */\n .replace(\n /([:a-zA-Z_-]*)(\\*{1,2})+/g,\n (_, parameterName: string | undefined, wildcard: string) => {\n const expression = '(.*)'\n\n if (!parameterName) {\n return expression\n }\n\n return parameterName.startsWith(':')\n ? `${parameterName}${wildcard}`\n : `${parameterName}${expression}`\n },\n )\n /**\n * Escape the port so that \"path-to-regexp\" can match\n * absolute URLs including port numbers.\n */\n .replace(/([^/])(:)(?=\\d+)/, '$1\\\\$2')\n /**\n * Escape the protocol so that \"path-to-regexp\" could match\n * absolute URL.\n * @see https://github.com/pillarjs/path-to-regexp/issues/259\n */\n .replace(/^([^/]+)(:)(?=\\/\\/)/, '$1\\\\$2')\n )\n}\n\n/**\n * Returns the result of matching given request URL against a mask.\n */\nexport function matchRequestUrl(url: URL, path: Path, baseUrl?: string): Match {\n const normalizedPath = normalizePath(path, baseUrl)\n const cleanPath =\n typeof normalizedPath === 'string'\n ? coercePath(normalizedPath)\n : normalizedPath\n\n const cleanUrl = getCleanUrl(url)\n const result = match(cleanPath, { decode: decodeURIComponent })(cleanUrl)\n const params = (result && (result.params as PathParams)) || {}\n\n return {\n matches: result !== false,\n params,\n }\n}\n\nexport function isPath(value: unknown): value is Path {\n return typeof value === 'string' || value instanceof RegExp\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAsB;AACtB,0BAA4B;AAC5B,2BAA8B;AAgBvB,SAAS,WAAW,MAAsB;AAC/C,SACE,KAMG;AAAA,IACC;AAAA,IACA,CAAC,GAAG,eAAmC,aAAqB;AAC1D,YAAM,aAAa;AAEnB,UAAI,CAAC,eAAe;AAClB,eAAO;AAAA,MACT;AAEA,aAAO,cAAc,WAAW,GAAG,IAC/B,GAAG,aAAa,GAAG,QAAQ,KAC3B,GAAG,aAAa,GAAG,UAAU;AAAA,IACnC;AAAA,EACF,EAKC,QAAQ,oBAAoB,QAAQ,EAMpC,QAAQ,uBAAuB,QAAQ;AAE9C;AAKO,SAAS,gBAAgB,KAAU,MAAY,SAAyB;AAC7E,QAAM,qBAAiB,oCAAc,MAAM,OAAO;AAClD,QAAM,YACJ,OAAO,mBAAmB,WACtB,WAAW,cAAc,IACzB;AAEN,QAAM,eAAW,iCAAY,GAAG;AAChC,QAAM,aAAS,6BAAM,WAAW,EAAE,QAAQ,mBAAmB,CAAC,EAAE,QAAQ;AACxE,QAAM,SAAU,UAAW,OAAO,UAA0B,CAAC;AAE7D,SAAO;AAAA,IACL,SAAS,WAAW;AAAA,IACpB;AAAA,EACF;AACF;AAEO,SAAS,OAAO,OAA+B;AACpD,SAAO,OAAO,UAAU,YAAY,iBAAiB;AACvD;","names":[]}
@@ -11,7 +11,7 @@ function coercePath(path) {
11
11
  }
12
12
  return parameterName.startsWith(":") ? `${parameterName}${wildcard}` : `${parameterName}${expression}`;
13
13
  }
14
- ).replace(/([^\/])(:)(?=\d+)/, "$1\\$2").replace(/^([^\/]+)(:)(?=\/\/)/, "$1\\$2");
14
+ ).replace(/([^/])(:)(?=\d+)/, "$1\\$2").replace(/^([^/]+)(:)(?=\/\/)/, "$1\\$2");
15
15
  }
16
16
  function matchRequestUrl(url, path, baseUrl) {
17
17
  const normalizedPath = normalizePath(path, baseUrl);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/utils/matching/matchRequestUrl.ts"],"sourcesContent":["import { match } from 'path-to-regexp'\nimport { getCleanUrl } from '@mswjs/interceptors'\nimport { normalizePath } from './normalizePath'\n\nexport type Path = string | RegExp\nexport type PathParams<KeyType extends keyof any = string> = {\n [ParamName in KeyType]?: string | ReadonlyArray<string>\n}\n\nexport interface Match {\n matches: boolean\n params?: PathParams\n}\n\n/**\n * Coerce a path supported by MSW into a path\n * supported by \"path-to-regexp\".\n */\nexport function coercePath(path: string): string {\n return (\n path\n /**\n * Replace wildcards (\"*\") with unnamed capturing groups\n * because \"path-to-regexp\" doesn't support wildcards.\n * Ignore path parameter' modifiers (i.e. \":name*\").\n */\n .replace(\n /([:a-zA-Z_-]*)(\\*{1,2})+/g,\n (_, parameterName: string | undefined, wildcard: string) => {\n const expression = '(.*)'\n\n if (!parameterName) {\n return expression\n }\n\n return parameterName.startsWith(':')\n ? `${parameterName}${wildcard}`\n : `${parameterName}${expression}`\n },\n )\n /**\n * Escape the port so that \"path-to-regexp\" can match\n * absolute URLs including port numbers.\n */\n .replace(/([^\\/])(:)(?=\\d+)/, '$1\\\\$2')\n /**\n * Escape the protocol so that \"path-to-regexp\" could match\n * absolute URL.\n * @see https://github.com/pillarjs/path-to-regexp/issues/259\n */\n .replace(/^([^\\/]+)(:)(?=\\/\\/)/, '$1\\\\$2')\n )\n}\n\n/**\n * Returns the result of matching given request URL against a mask.\n */\nexport function matchRequestUrl(url: URL, path: Path, baseUrl?: string): Match {\n const normalizedPath = normalizePath(path, baseUrl)\n const cleanPath =\n typeof normalizedPath === 'string'\n ? coercePath(normalizedPath)\n : normalizedPath\n\n const cleanUrl = getCleanUrl(url)\n const result = match(cleanPath, { decode: decodeURIComponent })(cleanUrl)\n const params = (result && (result.params as PathParams)) || {}\n\n return {\n matches: result !== false,\n params,\n }\n}\n\nexport function isPath(value: unknown): value is Path {\n return typeof value === 'string' || value instanceof RegExp\n}\n"],"mappings":"AAAA,SAAS,aAAa;AACtB,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAgBvB,SAAS,WAAW,MAAsB;AAC/C,SACE,KAMG;AAAA,IACC;AAAA,IACA,CAAC,GAAG,eAAmC,aAAqB;AAC1D,YAAM,aAAa;AAEnB,UAAI,CAAC,eAAe;AAClB,eAAO;AAAA,MACT;AAEA,aAAO,cAAc,WAAW,GAAG,IAC/B,GAAG,aAAa,GAAG,QAAQ,KAC3B,GAAG,aAAa,GAAG,UAAU;AAAA,IACnC;AAAA,EACF,EAKC,QAAQ,qBAAqB,QAAQ,EAMrC,QAAQ,wBAAwB,QAAQ;AAE/C;AAKO,SAAS,gBAAgB,KAAU,MAAY,SAAyB;AAC7E,QAAM,iBAAiB,cAAc,MAAM,OAAO;AAClD,QAAM,YACJ,OAAO,mBAAmB,WACtB,WAAW,cAAc,IACzB;AAEN,QAAM,WAAW,YAAY,GAAG;AAChC,QAAM,SAAS,MAAM,WAAW,EAAE,QAAQ,mBAAmB,CAAC,EAAE,QAAQ;AACxE,QAAM,SAAU,UAAW,OAAO,UAA0B,CAAC;AAE7D,SAAO;AAAA,IACL,SAAS,WAAW;AAAA,IACpB;AAAA,EACF;AACF;AAEO,SAAS,OAAO,OAA+B;AACpD,SAAO,OAAO,UAAU,YAAY,iBAAiB;AACvD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/utils/matching/matchRequestUrl.ts"],"sourcesContent":["import { match } from 'path-to-regexp'\nimport { getCleanUrl } from '@mswjs/interceptors'\nimport { normalizePath } from './normalizePath'\n\nexport type Path = string | RegExp\nexport type PathParams<KeyType extends keyof any = string> = {\n [ParamName in KeyType]?: string | ReadonlyArray<string>\n}\n\nexport interface Match {\n matches: boolean\n params?: PathParams\n}\n\n/**\n * Coerce a path supported by MSW into a path\n * supported by \"path-to-regexp\".\n */\nexport function coercePath(path: string): string {\n return (\n path\n /**\n * Replace wildcards (\"*\") with unnamed capturing groups\n * because \"path-to-regexp\" doesn't support wildcards.\n * Ignore path parameter' modifiers (i.e. \":name*\").\n */\n .replace(\n /([:a-zA-Z_-]*)(\\*{1,2})+/g,\n (_, parameterName: string | undefined, wildcard: string) => {\n const expression = '(.*)'\n\n if (!parameterName) {\n return expression\n }\n\n return parameterName.startsWith(':')\n ? `${parameterName}${wildcard}`\n : `${parameterName}${expression}`\n },\n )\n /**\n * Escape the port so that \"path-to-regexp\" can match\n * absolute URLs including port numbers.\n */\n .replace(/([^/])(:)(?=\\d+)/, '$1\\\\$2')\n /**\n * Escape the protocol so that \"path-to-regexp\" could match\n * absolute URL.\n * @see https://github.com/pillarjs/path-to-regexp/issues/259\n */\n .replace(/^([^/]+)(:)(?=\\/\\/)/, '$1\\\\$2')\n )\n}\n\n/**\n * Returns the result of matching given request URL against a mask.\n */\nexport function matchRequestUrl(url: URL, path: Path, baseUrl?: string): Match {\n const normalizedPath = normalizePath(path, baseUrl)\n const cleanPath =\n typeof normalizedPath === 'string'\n ? coercePath(normalizedPath)\n : normalizedPath\n\n const cleanUrl = getCleanUrl(url)\n const result = match(cleanPath, { decode: decodeURIComponent })(cleanUrl)\n const params = (result && (result.params as PathParams)) || {}\n\n return {\n matches: result !== false,\n params,\n }\n}\n\nexport function isPath(value: unknown): value is Path {\n return typeof value === 'string' || value instanceof RegExp\n}\n"],"mappings":"AAAA,SAAS,aAAa;AACtB,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAgBvB,SAAS,WAAW,MAAsB;AAC/C,SACE,KAMG;AAAA,IACC;AAAA,IACA,CAAC,GAAG,eAAmC,aAAqB;AAC1D,YAAM,aAAa;AAEnB,UAAI,CAAC,eAAe;AAClB,eAAO;AAAA,MACT;AAEA,aAAO,cAAc,WAAW,GAAG,IAC/B,GAAG,aAAa,GAAG,QAAQ,KAC3B,GAAG,aAAa,GAAG,UAAU;AAAA,IACnC;AAAA,EACF,EAKC,QAAQ,oBAAoB,QAAQ,EAMpC,QAAQ,uBAAuB,QAAQ;AAE9C;AAKO,SAAS,gBAAgB,KAAU,MAAY,SAAyB;AAC7E,QAAM,iBAAiB,cAAc,MAAM,OAAO;AAClD,QAAM,YACJ,OAAO,mBAAmB,WACtB,WAAW,cAAc,IACzB;AAEN,QAAM,WAAW,YAAY,GAAG;AAChC,QAAM,SAAS,MAAM,WAAW,EAAE,QAAQ,mBAAmB,CAAC,EAAE,QAAQ;AACxE,QAAM,SAAU,UAAW,OAAO,UAA0B,CAAC;AAE7D,SAAO;AAAA,IACL,SAAS,WAAW;AAAA,IACpB;AAAA,EACF;AACF;AAEO,SAAS,OAAO,OAA+B;AACpD,SAAO,OAAO,UAAU,YAAY,iBAAiB;AACvD;","names":[]}
@@ -22,7 +22,7 @@ __export(cleanUrl_exports, {
22
22
  getSearchParams: () => getSearchParams
23
23
  });
24
24
  module.exports = __toCommonJS(cleanUrl_exports);
25
- const REDUNDANT_CHARACTERS_EXP = /[\?|#].*$/g;
25
+ const REDUNDANT_CHARACTERS_EXP = /[?|#].*$/g;
26
26
  function getSearchParams(path) {
27
27
  return new URL(`/${path}`, "http://localhost").searchParams;
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/utils/url/cleanUrl.ts"],"sourcesContent":["const REDUNDANT_CHARACTERS_EXP = /[\\?|#].*$/g\n\nexport function getSearchParams(path: string) {\n return new URL(`/${path}`, 'http://localhost').searchParams\n}\n\n/**\n * Removes search parameters and the fragment\n * from a given URL string.\n */\nexport function cleanUrl(path: string): string {\n // If the path ends with an optional path parameter,\n // return it as-is.\n if (path.endsWith('?')) {\n return path\n }\n\n // Otherwise, remove the search and fragment from it.\n return path.replace(REDUNDANT_CHARACTERS_EXP, '')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAAM,2BAA2B;AAE1B,SAAS,gBAAgB,MAAc;AAC5C,SAAO,IAAI,IAAI,IAAI,IAAI,IAAI,kBAAkB,EAAE;AACjD;AAMO,SAAS,SAAS,MAAsB;AAG7C,MAAI,KAAK,SAAS,GAAG,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,SAAO,KAAK,QAAQ,0BAA0B,EAAE;AAClD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/utils/url/cleanUrl.ts"],"sourcesContent":["const REDUNDANT_CHARACTERS_EXP = /[?|#].*$/g\n\nexport function getSearchParams(path: string) {\n return new URL(`/${path}`, 'http://localhost').searchParams\n}\n\n/**\n * Removes search parameters and the fragment\n * from a given URL string.\n */\nexport function cleanUrl(path: string): string {\n // If the path ends with an optional path parameter,\n // return it as-is.\n if (path.endsWith('?')) {\n return path\n }\n\n // Otherwise, remove the search and fragment from it.\n return path.replace(REDUNDANT_CHARACTERS_EXP, '')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAAM,2BAA2B;AAE1B,SAAS,gBAAgB,MAAc;AAC5C,SAAO,IAAI,IAAI,IAAI,IAAI,IAAI,kBAAkB,EAAE;AACjD;AAMO,SAAS,SAAS,MAAsB;AAG7C,MAAI,KAAK,SAAS,GAAG,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,SAAO,KAAK,QAAQ,0BAA0B,EAAE;AAClD;","names":[]}
@@ -1,4 +1,4 @@
1
- const REDUNDANT_CHARACTERS_EXP = /[\?|#].*$/g;
1
+ const REDUNDANT_CHARACTERS_EXP = /[?|#].*$/g;
2
2
  function getSearchParams(path) {
3
3
  return new URL(`/${path}`, "http://localhost").searchParams;
4
4
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/utils/url/cleanUrl.ts"],"sourcesContent":["const REDUNDANT_CHARACTERS_EXP = /[\\?|#].*$/g\n\nexport function getSearchParams(path: string) {\n return new URL(`/${path}`, 'http://localhost').searchParams\n}\n\n/**\n * Removes search parameters and the fragment\n * from a given URL string.\n */\nexport function cleanUrl(path: string): string {\n // If the path ends with an optional path parameter,\n // return it as-is.\n if (path.endsWith('?')) {\n return path\n }\n\n // Otherwise, remove the search and fragment from it.\n return path.replace(REDUNDANT_CHARACTERS_EXP, '')\n}\n"],"mappings":"AAAA,MAAM,2BAA2B;AAE1B,SAAS,gBAAgB,MAAc;AAC5C,SAAO,IAAI,IAAI,IAAI,IAAI,IAAI,kBAAkB,EAAE;AACjD;AAMO,SAAS,SAAS,MAAsB;AAG7C,MAAI,KAAK,SAAS,GAAG,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,SAAO,KAAK,QAAQ,0BAA0B,EAAE;AAClD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/utils/url/cleanUrl.ts"],"sourcesContent":["const REDUNDANT_CHARACTERS_EXP = /[?|#].*$/g\n\nexport function getSearchParams(path: string) {\n return new URL(`/${path}`, 'http://localhost').searchParams\n}\n\n/**\n * Removes search parameters and the fragment\n * from a given URL string.\n */\nexport function cleanUrl(path: string): string {\n // If the path ends with an optional path parameter,\n // return it as-is.\n if (path.endsWith('?')) {\n return path\n }\n\n // Otherwise, remove the search and fragment from it.\n return path.replace(REDUNDANT_CHARACTERS_EXP, '')\n}\n"],"mappings":"AAAA,MAAM,2BAA2B;AAE1B,SAAS,gBAAgB,MAAc;AAC5C,SAAO,IAAI,IAAI,IAAI,IAAI,IAAI,kBAAkB,EAAE;AACjD;AAMO,SAAS,SAAS,MAAsB;AAG7C,MAAI,KAAK,SAAS,GAAG,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,SAAO,KAAK,QAAQ,0BAA0B,EAAE;AAClD;","names":[]}
@@ -22,6 +22,6 @@ __export(isAbsoluteUrl_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(isAbsoluteUrl_exports);
24
24
  function isAbsoluteUrl(url) {
25
- return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
25
+ return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
26
26
  }
27
27
  //# sourceMappingURL=isAbsoluteUrl.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/utils/url/isAbsoluteUrl.ts"],"sourcesContent":["/**\n * Determines if the given URL string is an absolute URL.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^([a-z][a-z\\d\\+\\-\\.]*:)?\\/\\//i.test(url)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,SAAS,cAAc,KAAsB;AAClD,SAAO,gCAAgC,KAAK,GAAG;AACjD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/utils/url/isAbsoluteUrl.ts"],"sourcesContent":["/**\n * Determines if the given URL string is an absolute URL.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,SAAS,cAAc,KAAsB;AAClD,SAAO,8BAA8B,KAAK,GAAG;AAC/C;","names":[]}
@@ -1,5 +1,5 @@
1
1
  function isAbsoluteUrl(url) {
2
- return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
2
+ return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
3
3
  }
4
4
  export {
5
5
  isAbsoluteUrl
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/utils/url/isAbsoluteUrl.ts"],"sourcesContent":["/**\n * Determines if the given URL string is an absolute URL.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^([a-z][a-z\\d\\+\\-\\.]*:)?\\/\\//i.test(url)\n}\n"],"mappings":"AAGO,SAAS,cAAc,KAAsB;AAClD,SAAO,gCAAgC,KAAK,GAAG;AACjD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/utils/url/isAbsoluteUrl.ts"],"sourcesContent":["/**\n * Determines if the given URL string is an absolute URL.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url)\n}\n"],"mappings":"AAGO,SAAS,cAAc,KAAsB;AAClD,SAAO,8BAA8B,KAAK,GAAG;AAC/C;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/ws/WebSocketIndexedDBClientStore.ts"],"sourcesContent":["import { DeferredPromise } from '@open-draft/deferred-promise'\nimport { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'\nimport {\n type SerializedWebSocketClient,\n WebSocketClientStore,\n} from './WebSocketClientStore'\n\nconst DB_NAME = 'msw-websocket-clients'\nconst DB_STORE_NAME = 'clients'\n\nexport class WebSocketIndexedDBClientStore implements WebSocketClientStore {\n private db: Promise<IDBDatabase>\n\n constructor() {\n this.db = this.createDatabase()\n }\n\n public async add(client: WebSocketClientConnectionProtocol): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n /**\n * @note Use `.put()` instead of `.add()` to allow setting clients\n * that already exist in the database. This can happen if a single page\n * has multiple event handlers. Each handler will receive the \"connection\"\n * event in parallel, and try to set that WebSocket client in the database.\n */\n const request = store.put({\n id: client.id,\n url: client.url.href,\n } satisfies SerializedWebSocketClient)\n\n request.onsuccess = () => {\n promise.resolve()\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(request.error)\n promise.reject(\n new Error(\n `Failed to add WebSocket client \"${client.id}\". There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async getAll(): Promise<Array<SerializedWebSocketClient>> {\n const promise = new DeferredPromise<Array<SerializedWebSocketClient>>()\n const store = await this.getStore()\n const request = store.getAll() as IDBRequest<\n Array<SerializedWebSocketClient>\n >\n\n request.onsuccess = () => {\n promise.resolve(request.result)\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.log(request.error)\n promise.reject(\n new Error(\n `Failed to get all WebSocket clients. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async deleteMany(clientIds: Array<string>): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n for (const clientId of clientIds) {\n store.delete(clientId)\n }\n\n store.transaction.oncomplete = () => {\n promise.resolve()\n }\n store.transaction.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n `Failed to delete WebSocket clients [${clientIds.join(', ')}]. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n private async createDatabase(): Promise<IDBDatabase> {\n const promise = new DeferredPromise<IDBDatabase>()\n const request = indexedDB.open(DB_NAME, 1)\n\n request.onsuccess = ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return promise.resolve(db)\n }\n }\n\n request.onupgradeneeded = async ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return\n }\n\n const store = db.createObjectStore(DB_STORE_NAME, { keyPath: 'id' })\n store.transaction.oncomplete = () => {\n promise.resolve(db)\n }\n store.transaction.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n 'Failed to create WebSocket client store. There is likely an additional output above.',\n ),\n )\n }\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(request.error)\n promise.reject(\n new Error(\n 'Failed to open an IndexedDB database. There is likely an additional output above.',\n ),\n )\n }\n\n return promise\n }\n\n private async getStore(): Promise<IDBObjectStore> {\n const db = await this.db\n return db.transaction(DB_STORE_NAME, 'readwrite').objectStore(DB_STORE_NAME)\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/core/ws/WebSocketIndexedDBClientStore.ts"],"sourcesContent":["import { DeferredPromise } from '@open-draft/deferred-promise'\nimport { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'\nimport {\n type SerializedWebSocketClient,\n WebSocketClientStore,\n} from './WebSocketClientStore'\n\nconst DB_NAME = 'msw-websocket-clients'\nconst DB_STORE_NAME = 'clients'\n\nexport class WebSocketIndexedDBClientStore implements WebSocketClientStore {\n private db: Promise<IDBDatabase>\n\n constructor() {\n this.db = this.createDatabase()\n }\n\n public async add(client: WebSocketClientConnectionProtocol): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n /**\n * @note Use `.put()` instead of `.add()` to allow setting clients\n * that already exist in the database. This can happen if a single page\n * has multiple event handlers. Each handler will receive the \"connection\"\n * event in parallel, and try to set that WebSocket client in the database.\n */\n const request = store.put({\n id: client.id,\n url: client.url.href,\n } satisfies SerializedWebSocketClient)\n\n request.onsuccess = () => {\n promise.resolve()\n }\n request.onerror = () => {\n console.error(request.error)\n promise.reject(\n new Error(\n `Failed to add WebSocket client \"${client.id}\". There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async getAll(): Promise<Array<SerializedWebSocketClient>> {\n const promise = new DeferredPromise<Array<SerializedWebSocketClient>>()\n const store = await this.getStore()\n const request = store.getAll() as IDBRequest<\n Array<SerializedWebSocketClient>\n >\n\n request.onsuccess = () => {\n promise.resolve(request.result)\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.log(request.error)\n promise.reject(\n new Error(\n `Failed to get all WebSocket clients. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async deleteMany(clientIds: Array<string>): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n for (const clientId of clientIds) {\n store.delete(clientId)\n }\n\n store.transaction.oncomplete = () => {\n promise.resolve()\n }\n store.transaction.onerror = () => {\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n `Failed to delete WebSocket clients [${clientIds.join(', ')}]. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n private async createDatabase(): Promise<IDBDatabase> {\n const promise = new DeferredPromise<IDBDatabase>()\n const request = indexedDB.open(DB_NAME, 1)\n\n request.onsuccess = ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return promise.resolve(db)\n }\n }\n\n request.onupgradeneeded = async ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return\n }\n\n const store = db.createObjectStore(DB_STORE_NAME, { keyPath: 'id' })\n store.transaction.oncomplete = () => {\n promise.resolve(db)\n }\n store.transaction.onerror = () => {\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n 'Failed to create WebSocket client store. There is likely an additional output above.',\n ),\n )\n }\n }\n request.onerror = () => {\n console.error(request.error)\n promise.reject(\n new Error(\n 'Failed to open an IndexedDB database. There is likely an additional output above.',\n ),\n )\n }\n\n return promise\n }\n\n private async getStore(): Promise<IDBObjectStore> {\n const db = await this.db\n return db.transaction(DB_STORE_NAME, 'readwrite').objectStore(DB_STORE_NAME)\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/ws/WebSocketIndexedDBClientStore.ts"],"sourcesContent":["import { DeferredPromise } from '@open-draft/deferred-promise'\nimport { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'\nimport {\n type SerializedWebSocketClient,\n WebSocketClientStore,\n} from './WebSocketClientStore'\n\nconst DB_NAME = 'msw-websocket-clients'\nconst DB_STORE_NAME = 'clients'\n\nexport class WebSocketIndexedDBClientStore implements WebSocketClientStore {\n private db: Promise<IDBDatabase>\n\n constructor() {\n this.db = this.createDatabase()\n }\n\n public async add(client: WebSocketClientConnectionProtocol): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n /**\n * @note Use `.put()` instead of `.add()` to allow setting clients\n * that already exist in the database. This can happen if a single page\n * has multiple event handlers. Each handler will receive the \"connection\"\n * event in parallel, and try to set that WebSocket client in the database.\n */\n const request = store.put({\n id: client.id,\n url: client.url.href,\n } satisfies SerializedWebSocketClient)\n\n request.onsuccess = () => {\n promise.resolve()\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(request.error)\n promise.reject(\n new Error(\n `Failed to add WebSocket client \"${client.id}\". There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async getAll(): Promise<Array<SerializedWebSocketClient>> {\n const promise = new DeferredPromise<Array<SerializedWebSocketClient>>()\n const store = await this.getStore()\n const request = store.getAll() as IDBRequest<\n Array<SerializedWebSocketClient>\n >\n\n request.onsuccess = () => {\n promise.resolve(request.result)\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.log(request.error)\n promise.reject(\n new Error(\n `Failed to get all WebSocket clients. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async deleteMany(clientIds: Array<string>): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n for (const clientId of clientIds) {\n store.delete(clientId)\n }\n\n store.transaction.oncomplete = () => {\n promise.resolve()\n }\n store.transaction.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n `Failed to delete WebSocket clients [${clientIds.join(', ')}]. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n private async createDatabase(): Promise<IDBDatabase> {\n const promise = new DeferredPromise<IDBDatabase>()\n const request = indexedDB.open(DB_NAME, 1)\n\n request.onsuccess = ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return promise.resolve(db)\n }\n }\n\n request.onupgradeneeded = async ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return\n }\n\n const store = db.createObjectStore(DB_STORE_NAME, { keyPath: 'id' })\n store.transaction.oncomplete = () => {\n promise.resolve(db)\n }\n store.transaction.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n 'Failed to create WebSocket client store. There is likely an additional output above.',\n ),\n )\n }\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.error(request.error)\n promise.reject(\n new Error(\n 'Failed to open an IndexedDB database. There is likely an additional output above.',\n ),\n )\n }\n\n return promise\n }\n\n private async getStore(): Promise<IDBObjectStore> {\n const db = await this.db\n return db.transaction(DB_STORE_NAME, 'readwrite').objectStore(DB_STORE_NAME)\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/core/ws/WebSocketIndexedDBClientStore.ts"],"sourcesContent":["import { DeferredPromise } from '@open-draft/deferred-promise'\nimport { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'\nimport {\n type SerializedWebSocketClient,\n WebSocketClientStore,\n} from './WebSocketClientStore'\n\nconst DB_NAME = 'msw-websocket-clients'\nconst DB_STORE_NAME = 'clients'\n\nexport class WebSocketIndexedDBClientStore implements WebSocketClientStore {\n private db: Promise<IDBDatabase>\n\n constructor() {\n this.db = this.createDatabase()\n }\n\n public async add(client: WebSocketClientConnectionProtocol): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n /**\n * @note Use `.put()` instead of `.add()` to allow setting clients\n * that already exist in the database. This can happen if a single page\n * has multiple event handlers. Each handler will receive the \"connection\"\n * event in parallel, and try to set that WebSocket client in the database.\n */\n const request = store.put({\n id: client.id,\n url: client.url.href,\n } satisfies SerializedWebSocketClient)\n\n request.onsuccess = () => {\n promise.resolve()\n }\n request.onerror = () => {\n console.error(request.error)\n promise.reject(\n new Error(\n `Failed to add WebSocket client \"${client.id}\". There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async getAll(): Promise<Array<SerializedWebSocketClient>> {\n const promise = new DeferredPromise<Array<SerializedWebSocketClient>>()\n const store = await this.getStore()\n const request = store.getAll() as IDBRequest<\n Array<SerializedWebSocketClient>\n >\n\n request.onsuccess = () => {\n promise.resolve(request.result)\n }\n request.onerror = () => {\n // eslint-disable-next-line no-console\n console.log(request.error)\n promise.reject(\n new Error(\n `Failed to get all WebSocket clients. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n public async deleteMany(clientIds: Array<string>): Promise<void> {\n const promise = new DeferredPromise<void>()\n const store = await this.getStore()\n\n for (const clientId of clientIds) {\n store.delete(clientId)\n }\n\n store.transaction.oncomplete = () => {\n promise.resolve()\n }\n store.transaction.onerror = () => {\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n `Failed to delete WebSocket clients [${clientIds.join(', ')}]. There is likely an additional output above.`,\n ),\n )\n }\n\n return promise\n }\n\n private async createDatabase(): Promise<IDBDatabase> {\n const promise = new DeferredPromise<IDBDatabase>()\n const request = indexedDB.open(DB_NAME, 1)\n\n request.onsuccess = ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return promise.resolve(db)\n }\n }\n\n request.onupgradeneeded = async ({ currentTarget }) => {\n const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n return\n }\n\n const store = db.createObjectStore(DB_STORE_NAME, { keyPath: 'id' })\n store.transaction.oncomplete = () => {\n promise.resolve(db)\n }\n store.transaction.onerror = () => {\n console.error(store.transaction.error)\n promise.reject(\n new Error(\n 'Failed to create WebSocket client store. There is likely an additional output above.',\n ),\n )\n }\n }\n request.onerror = () => {\n console.error(request.error)\n promise.reject(\n new Error(\n 'Failed to open an IndexedDB database. There is likely an additional output above.',\n ),\n )\n }\n\n return promise\n }\n\n private async getStore(): Promise<IDBObjectStore> {\n const db = await this.db\n return db.transaction(DB_STORE_NAME, 'readwrite').objectStore(DB_STORE_NAME)\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/ws/utils/attachWebSocketLogger.ts"],"sourcesContent":["import type {\n WebSocketClientConnection,\n WebSocketConnectionData,\n WebSocketData,\n} from '@mswjs/interceptors/WebSocket'\nimport { devUtils } from '../../utils/internal/devUtils'\nimport { getTimestamp } from '../../utils/logging/getTimestamp'\nimport { toPublicUrl } from '../../utils/request/toPublicUrl'\nimport { getMessageLength } from './getMessageLength'\nimport { getPublicData } from './getPublicData'\n\nconst colors = {\n system: '#3b82f6',\n outgoing: '#22c55e',\n incoming: '#ef4444',\n mocked: '#ff6a33',\n}\n\nexport function attachWebSocketLogger(\n connection: WebSocketConnectionData,\n): void {\n const { client, server } = connection\n\n logConnectionOpen(client)\n\n // Log the events sent from the WebSocket client.\n // WebSocket client connection object is written from the\n // server's perspective so these message events are outgoing.\n /**\n * @todo Provide the reference to the exact event handler\n * that called this `client.send()`.\n */\n client.addEventListener('message', (event) => {\n logOutgoingClientMessage(event)\n })\n\n client.addEventListener('close', (event) => {\n logConnectionClose(event)\n })\n\n // Log client errors (connection closures due to errors).\n client.socket.addEventListener('error', (event) => {\n logClientError(event)\n })\n\n client.send = new Proxy(client.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n })\n\n queueMicrotask(() => {\n logIncomingMockedClientMessage(messageEvent)\n })\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n server.addEventListener(\n 'open',\n () => {\n server.addEventListener('message', (event) => {\n logIncomingServerMessage(event)\n })\n },\n { once: true },\n )\n\n // Log outgoing client events initiated by the event handler.\n // The actual client never sent these but the handler did.\n server.send = new Proxy(server.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n })\n\n logOutgoingMockedClientMessage(messageEvent)\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n}\n\n/**\n * Prints the WebSocket connection.\n * This is meant to be logged by every WebSocket handler\n * that intercepted this connection. This helps you see\n * what handlers observe this connection.\n */\nexport function logConnectionOpen(client: WebSocketClientConnection) {\n const publicUrl = toPublicUrl(client.url)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(`${getTimestamp()} %c▶%c ${publicUrl}`),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log('Client:', client.socket)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\nfunction logConnectionClose(event: CloseEvent) {\n const target = event.target as WebSocket\n const publicUrl = toPublicUrl(target.url)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c■%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\nfunction logClientError(event: Event) {\n const socket = event.target as WebSocket\n const publicUrl = toPublicUrl(socket.url)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c\\u00D7%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message.\n */\nasync function logOutgoingClientMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇡' : '⬆'\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.outgoing}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `server.send()` in the event handler.\n */\nasync function logOutgoingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬆%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `client.send()` in the event handler.\n */\nasync function logIncomingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬇%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\nasync function logIncomingServerMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇣' : '⬇'\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.incoming}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,sBAAyB;AACzB,0BAA6B;AAC7B,yBAA4B;AAC5B,8BAAiC;AACjC,2BAA8B;AAE9B,MAAM,SAAS;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AACV;AAEO,SAAS,sBACd,YACM;AACN,QAAM,EAAE,QAAQ,OAAO,IAAI;AAE3B,oBAAkB,MAAM;AASxB,SAAO,iBAAiB,WAAW,CAAC,UAAU;AAC5C,6BAAyB,KAAK;AAAA,EAChC,CAAC;AAED,SAAO,iBAAiB,SAAS,CAAC,UAAU;AAC1C,uBAAmB,KAAK;AAAA,EAC1B,CAAC;AAGD,SAAO,OAAO,iBAAiB,SAAS,CAAC,UAAU;AACjD,mBAAe,KAAK;AAAA,EACtB,CAAC;AAED,SAAO,OAAO,IAAI,MAAM,OAAO,MAAM;AAAA,IACnC,MAAM,QAAQ,SAAS,MAAM;AAC3B,YAAM,CAAC,IAAI,IAAI;AACf,YAAM,eAAe,IAAI,aAAa,WAAW,EAAE,KAAK,CAAC;AACzD,aAAO,iBAAiB,cAAc;AAAA,QACpC,eAAe;AAAA,UACb,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,OAAO,OAAO;AAAA,QAChB;AAAA,QACA,QAAQ;AAAA,UACN,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,OAAO,OAAO;AAAA,QAChB;AAAA,MACF,CAAC;AAED,qBAAe,MAAM;AACnB,uCAA+B,YAAY;AAAA,MAC7C,CAAC;AAED,aAAO,QAAQ,MAAM,QAAQ,SAAS,IAAI;AAAA,IAC5C;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AACJ,aAAO,iBAAiB,WAAW,CAAC,UAAU;AAC5C,iCAAyB,KAAK;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,IACA,EAAE,MAAM,KAAK;AAAA,EACf;AAIA,SAAO,OAAO,IAAI,MAAM,OAAO,MAAM;AAAA,IACnC,MAAM,QAAQ,SAAS,MAAM;AAC3B,YAAM,CAAC,IAAI,IAAI;AACf,YAAM,eAAe,IAAI,aAAa,WAAW,EAAE,KAAK,CAAC;AACzD,aAAO,iBAAiB,cAAc;AAAA,QACpC,eAAe;AAAA,UACb,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,OAAO,OAAO;AAAA,QAChB;AAAA,QACA,QAAQ;AAAA,UACN,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,OAAO,OAAO;AAAA,QAChB;AAAA,MACF,CAAC;AAED,qCAA+B,YAAY;AAE3C,aAAO,QAAQ,MAAM,QAAQ,SAAS,IAAI;AAAA,IAC5C;AAAA,EACF,CAAC;AACH;AAQO,SAAS,kBAAkB,QAAmC;AACnE,QAAM,gBAAY,gCAAY,OAAO,GAAG;AAGxC,UAAQ;AAAA,IACN,yBAAS,cAAc,OAAG,kCAAa,CAAC,eAAU,SAAS,EAAE;AAAA,IAC7D,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,UAAQ,IAAI,WAAW,OAAO,MAAM;AAEpC,UAAQ,SAAS;AACnB;AAEA,SAAS,mBAAmB,OAAmB;AAC7C,QAAM,SAAS,MAAM;AACrB,QAAM,gBAAY,gCAAY,OAAO,GAAG;AAGxC,UAAQ;AAAA,IACN,yBAAS;AAAA,MACP,OAAG,kCAAa,EAAE,cAAc,KAAK,CAAC,CAAC,eAAU,SAAS;AAAA,IAC5D;AAAA,IACA,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AAEjB,UAAQ,SAAS;AACnB;AAEA,SAAS,eAAe,OAAc;AACpC,QAAM,SAAS,MAAM;AACrB,QAAM,gBAAY,gCAAY,OAAO,GAAG;AAGxC,UAAQ;AAAA,IACN,yBAAS;AAAA,MACP,OAAG,kCAAa,EAAE,cAAc,KAAK,CAAC,CAAC,aAAe,SAAS;AAAA,IACjE;AAAA,IACA,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AAEjB,UAAQ,SAAS;AACnB;AAKA,eAAe,yBAAyB,OAAoC;AAC1E,QAAM,iBAAa,0CAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,UAAM,oCAAc,MAAM,IAAI;AACjD,QAAM,QAAQ,MAAM,mBAAmB,WAAM;AAG7C,UAAQ;AAAA,IACN,yBAAS;AAAA,MACP,OAAG,kCAAa,EAAE,cAAc,KAAK,CAAC,CAAC,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU;AAAA,IACpF;AAAA,IACA,SAAS,OAAO,QAAQ;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AAEjB,UAAQ,SAAS;AACnB;AAMA,eAAe,+BACb,OACA;AACA,QAAM,iBAAa,0CAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,UAAM,oCAAc,MAAM,IAAI;AAGjD,UAAQ;AAAA,IACN,yBAAS;AAAA,MACP,OAAG,kCAAa,EAAE,cAAc,KAAK,CAAC,CAAC,eAAU,UAAU,MAAM,UAAU;AAAA,IAC7E;AAAA,IACA,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AAEjB,UAAQ,SAAS;AACnB;AAMA,eAAe,+BACb,OACA;AACA,QAAM,iBAAa,0CAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,UAAM,oCAAc,MAAM,IAAI;AAGjD,UAAQ;AAAA,IACN,yBAAS;AAAA,MACP,OAAG,kCAAa,EAAE,cAAc,KAAK,CAAC,CAAC,eAAU,UAAU,MAAM,UAAU;AAAA,IAC7E;AAAA,IACA,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AAEjB,UAAQ,SAAS;AACnB;AAEA,eAAe,yBAAyB,OAAoC;AAC1E,QAAM,iBAAa,0CAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,UAAM,oCAAc,MAAM,IAAI;AACjD,QAAM,QAAQ,MAAM,mBAAmB,WAAM;AAG7C,UAAQ;AAAA,IACN,yBAAS;AAAA,MACP,OAAG,kCAAa,EAAE,cAAc,KAAK,CAAC,CAAC,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU;AAAA,IACpF;AAAA,IACA,SAAS,OAAO,QAAQ;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AAEjB,UAAQ,SAAS;AACnB;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/ws/utils/attachWebSocketLogger.ts"],"sourcesContent":["import type {\n WebSocketClientConnection,\n WebSocketConnectionData,\n WebSocketData,\n} from '@mswjs/interceptors/WebSocket'\nimport { devUtils } from '../../utils/internal/devUtils'\nimport { getTimestamp } from '../../utils/logging/getTimestamp'\nimport { toPublicUrl } from '../../utils/request/toPublicUrl'\nimport { getMessageLength } from './getMessageLength'\nimport { getPublicData } from './getPublicData'\n\nconst colors = {\n system: '#3b82f6',\n outgoing: '#22c55e',\n incoming: '#ef4444',\n mocked: '#ff6a33',\n}\n\nexport function attachWebSocketLogger(\n connection: WebSocketConnectionData,\n): void {\n const { client, server } = connection\n\n logConnectionOpen(client)\n\n // Log the events sent from the WebSocket client.\n // WebSocket client connection object is written from the\n // server's perspective so these message events are outgoing.\n /**\n * @todo Provide the reference to the exact event handler\n * that called this `client.send()`.\n */\n client.addEventListener('message', (event) => {\n logOutgoingClientMessage(event)\n })\n\n client.addEventListener('close', (event) => {\n logConnectionClose(event)\n })\n\n // Log client errors (connection closures due to errors).\n client.socket.addEventListener('error', (event) => {\n logClientError(event)\n })\n\n client.send = new Proxy(client.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n })\n\n queueMicrotask(() => {\n logIncomingMockedClientMessage(messageEvent)\n })\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n server.addEventListener(\n 'open',\n () => {\n server.addEventListener('message', (event) => {\n logIncomingServerMessage(event)\n })\n },\n { once: true },\n )\n\n // Log outgoing client events initiated by the event handler.\n // The actual client never sent these but the handler did.\n server.send = new Proxy(server.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n })\n\n logOutgoingMockedClientMessage(messageEvent)\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n}\n\n/**\n * Prints the WebSocket connection.\n * This is meant to be logged by every WebSocket handler\n * that intercepted this connection. This helps you see\n * what handlers observe this connection.\n */\nexport function logConnectionOpen(client: WebSocketClientConnection) {\n const publicUrl = toPublicUrl(client.url)\n\n console.groupCollapsed(\n devUtils.formatMessage(`${getTimestamp()} %c▶%c ${publicUrl}`),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log('Client:', client.socket)\n console.groupEnd()\n}\n\nfunction logConnectionClose(event: CloseEvent) {\n const target = event.target as WebSocket\n const publicUrl = toPublicUrl(target.url)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c■%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\nfunction logClientError(event: Event) {\n const socket = event.target as WebSocket\n const publicUrl = toPublicUrl(socket.url)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c\\u00D7%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message.\n */\nasync function logOutgoingClientMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇡' : '⬆'\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.outgoing}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `server.send()` in the event handler.\n */\nasync function logOutgoingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬆%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `client.send()` in the event handler.\n */\nasync function logIncomingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬇%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\nasync function logIncomingServerMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇣' : '⬇'\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.incoming}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/ws/utils/attachWebSocketLogger.ts"],"sourcesContent":["import type {\n WebSocketClientConnection,\n WebSocketConnectionData,\n WebSocketData,\n} from '@mswjs/interceptors/WebSocket'\nimport { devUtils } from '../../utils/internal/devUtils'\nimport { getTimestamp } from '../../utils/logging/getTimestamp'\nimport { toPublicUrl } from '../../utils/request/toPublicUrl'\nimport { getMessageLength } from './getMessageLength'\nimport { getPublicData } from './getPublicData'\n\nconst colors = {\n system: '#3b82f6',\n outgoing: '#22c55e',\n incoming: '#ef4444',\n mocked: '#ff6a33',\n}\n\nexport function attachWebSocketLogger(\n connection: WebSocketConnectionData,\n): void {\n const { client, server } = connection\n\n logConnectionOpen(client)\n\n // Log the events sent from the WebSocket client.\n // WebSocket client connection object is written from the\n // server's perspective so these message events are outgoing.\n /**\n * @todo Provide the reference to the exact event handler\n * that called this `client.send()`.\n */\n client.addEventListener('message', (event) => {\n logOutgoingClientMessage(event)\n })\n\n client.addEventListener('close', (event) => {\n logConnectionClose(event)\n })\n\n // Log client errors (connection closures due to errors).\n client.socket.addEventListener('error', (event) => {\n logClientError(event)\n })\n\n client.send = new Proxy(client.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n })\n\n queueMicrotask(() => {\n logIncomingMockedClientMessage(messageEvent)\n })\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n server.addEventListener(\n 'open',\n () => {\n server.addEventListener('message', (event) => {\n logIncomingServerMessage(event)\n })\n },\n { once: true },\n )\n\n // Log outgoing client events initiated by the event handler.\n // The actual client never sent these but the handler did.\n server.send = new Proxy(server.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n })\n\n logOutgoingMockedClientMessage(messageEvent)\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n}\n\n/**\n * Prints the WebSocket connection.\n * This is meant to be logged by every WebSocket handler\n * that intercepted this connection. This helps you see\n * what handlers observe this connection.\n */\nexport function logConnectionOpen(client: WebSocketClientConnection) {\n const publicUrl = toPublicUrl(client.url)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(`${getTimestamp()} %c▶%c ${publicUrl}`),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log('Client:', client.socket)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\nfunction logConnectionClose(event: CloseEvent) {\n const target = event.target as WebSocket\n const publicUrl = toPublicUrl(target.url)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c■%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\nfunction logClientError(event: Event) {\n const socket = event.target as WebSocket\n const publicUrl = toPublicUrl(socket.url)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c\\u00D7%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message.\n */\nasync function logOutgoingClientMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇡' : '⬆'\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.outgoing}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `server.send()` in the event handler.\n */\nasync function logOutgoingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬆%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `client.send()` in the event handler.\n */\nasync function logIncomingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬇%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n\nasync function logIncomingServerMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇣' : '⬇'\n\n // eslint-disable-next-line no-console\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.incoming}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n // eslint-disable-next-line no-console\n console.groupEnd()\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/ws/utils/attachWebSocketLogger.ts"],"sourcesContent":["import type {\n WebSocketClientConnection,\n WebSocketConnectionData,\n WebSocketData,\n} from '@mswjs/interceptors/WebSocket'\nimport { devUtils } from '../../utils/internal/devUtils'\nimport { getTimestamp } from '../../utils/logging/getTimestamp'\nimport { toPublicUrl } from '../../utils/request/toPublicUrl'\nimport { getMessageLength } from './getMessageLength'\nimport { getPublicData } from './getPublicData'\n\nconst colors = {\n system: '#3b82f6',\n outgoing: '#22c55e',\n incoming: '#ef4444',\n mocked: '#ff6a33',\n}\n\nexport function attachWebSocketLogger(\n connection: WebSocketConnectionData,\n): void {\n const { client, server } = connection\n\n logConnectionOpen(client)\n\n // Log the events sent from the WebSocket client.\n // WebSocket client connection object is written from the\n // server's perspective so these message events are outgoing.\n /**\n * @todo Provide the reference to the exact event handler\n * that called this `client.send()`.\n */\n client.addEventListener('message', (event) => {\n logOutgoingClientMessage(event)\n })\n\n client.addEventListener('close', (event) => {\n logConnectionClose(event)\n })\n\n // Log client errors (connection closures due to errors).\n client.socket.addEventListener('error', (event) => {\n logClientError(event)\n })\n\n client.send = new Proxy(client.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: client.socket,\n },\n })\n\n queueMicrotask(() => {\n logIncomingMockedClientMessage(messageEvent)\n })\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n server.addEventListener(\n 'open',\n () => {\n server.addEventListener('message', (event) => {\n logIncomingServerMessage(event)\n })\n },\n { once: true },\n )\n\n // Log outgoing client events initiated by the event handler.\n // The actual client never sent these but the handler did.\n server.send = new Proxy(server.send, {\n apply(target, thisArg, args) {\n const [data] = args\n const messageEvent = new MessageEvent('message', { data })\n Object.defineProperties(messageEvent, {\n currentTarget: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n target: {\n enumerable: true,\n writable: false,\n value: server.socket,\n },\n })\n\n logOutgoingMockedClientMessage(messageEvent)\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n}\n\n/**\n * Prints the WebSocket connection.\n * This is meant to be logged by every WebSocket handler\n * that intercepted this connection. This helps you see\n * what handlers observe this connection.\n */\nexport function logConnectionOpen(client: WebSocketClientConnection) {\n const publicUrl = toPublicUrl(client.url)\n\n console.groupCollapsed(\n devUtils.formatMessage(`${getTimestamp()} %c▶%c ${publicUrl}`),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log('Client:', client.socket)\n console.groupEnd()\n}\n\nfunction logConnectionClose(event: CloseEvent) {\n const target = event.target as WebSocket\n const publicUrl = toPublicUrl(target.url)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c■%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\nfunction logClientError(event: Event) {\n const socket = event.target as WebSocket\n const publicUrl = toPublicUrl(socket.url)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c\\u00D7%c ${publicUrl}`,\n ),\n `color:${colors.system}`,\n 'color:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message.\n */\nasync function logOutgoingClientMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇡' : '⬆'\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.outgoing}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `server.send()` in the event handler.\n */\nasync function logOutgoingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬆%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `client.send()` in the event handler.\n */\nasync function logIncomingMockedClientMessage(\n event: MessageEvent<WebSocketData>,\n) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c⬇%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.mocked}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n\nasync function logIncomingServerMessage(event: MessageEvent<WebSocketData>) {\n const byteLength = getMessageLength(event.data)\n const publicData = await getPublicData(event.data)\n const arrow = event.defaultPrevented ? '⇣' : '⬇'\n\n console.groupCollapsed(\n devUtils.formatMessage(\n `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n ),\n `color:${colors.incoming}`,\n 'color:inherit',\n 'color:gray;font-weight:normal',\n 'color:inherit;font-weight:inherit',\n )\n // eslint-disable-next-line no-console\n console.log(event)\n console.groupEnd()\n}\n"],"mappings":"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","names":[]}