{"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\nexport const 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":"AAKA,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAEvB,MAAM,SAAS;AAAA,EACpB,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,YAAY,YAAY,OAAO,GAAG;AAExC,UAAQ;AAAA,IACN,SAAS,cAAc,GAAG,aAAa,CAAC,eAAU,SAAS,EAAE;AAAA,IAC7D,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,UAAQ,IAAI,WAAW,OAAO,MAAM;AACpC,UAAQ,SAAS;AACnB;AAEA,SAAS,mBAAmB,OAAmB;AAC7C,QAAM,SAAS,MAAM;AACrB,QAAM,YAAY,YAAY,OAAO,GAAG;AAExC,UAAQ;AAAA,IACN,SAAS;AAAA,MACP,GAAG,aAAa,EAAE,cAAc,KAAK,CAAC,CAAC,eAAU,SAAS;AAAA,IAC5D;AAAA,IACA,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AACjB,UAAQ,SAAS;AACnB;AAEA,SAAS,eAAe,OAAc;AACpC,QAAM,SAAS,MAAM;AACrB,QAAM,YAAY,YAAY,OAAO,GAAG;AAExC,UAAQ;AAAA,IACN,SAAS;AAAA,MACP,GAAG,aAAa,EAAE,cAAc,KAAK,CAAC,CAAC,aAAe,SAAS;AAAA,IACjE;AAAA,IACA,SAAS,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,UAAQ,IAAI,KAAK;AACjB,UAAQ,SAAS;AACnB;AAKA,eAAe,yBAAyB,OAAoC;AAC1E,QAAM,aAAa,iBAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,MAAM,cAAc,MAAM,IAAI;AACjD,QAAM,QAAQ,MAAM,mBAAmB,WAAM;AAE7C,UAAQ;AAAA,IACN,SAAS;AAAA,MACP,GAAG,aAAa,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;AACjB,UAAQ,SAAS;AACnB;AAMA,eAAe,+BACb,OACA;AACA,QAAM,aAAa,iBAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,MAAM,cAAc,MAAM,IAAI;AAEjD,UAAQ;AAAA,IACN,SAAS;AAAA,MACP,GAAG,aAAa,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;AACjB,UAAQ,SAAS;AACnB;AAMA,eAAe,+BACb,OACA;AACA,QAAM,aAAa,iBAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,MAAM,cAAc,MAAM,IAAI;AAEjD,UAAQ;AAAA,IACN,SAAS;AAAA,MACP,GAAG,aAAa,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;AACjB,UAAQ,SAAS;AACnB;AAEA,eAAe,yBAAyB,OAAoC;AAC1E,QAAM,aAAa,iBAAiB,MAAM,IAAI;AAC9C,QAAM,aAAa,MAAM,cAAc,MAAM,IAAI;AACjD,QAAM,QAAQ,MAAM,mBAAmB,WAAM;AAE7C,UAAQ;AAAA,IACN,SAAS;AAAA,MACP,GAAG,aAAa,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;AACjB,UAAQ,SAAS;AACnB;","names":[]}