{"version":3,"sources":["../../../src/core/handlers/WebSocketHandler.ts"],"sourcesContent":["import { Emitter } from 'strict-event-emitter'\nimport { createRequestId } from '@mswjs/interceptors'\nimport type { WebSocketConnectionData } from '@mswjs/interceptors/WebSocket'\nimport {\n  type Match,\n  type Path,\n  type PathParams,\n  matchRequestUrl,\n} from '../utils/matching/matchRequestUrl'\nimport { getCallFrame } from '../utils/internal/getCallFrame'\nimport type { HandlerKind } from './common'\n\ntype WebSocketHandlerParsedResult = {\n  match: Match\n}\n\nexport type WebSocketHandlerEventMap = {\n  connection: [args: WebSocketHandlerConnection]\n}\n\nexport interface WebSocketHandlerConnection extends WebSocketConnectionData {\n  params: PathParams\n}\n\nexport const kEmitter = Symbol('kEmitter')\nexport const kDispatchEvent = Symbol('kDispatchEvent')\nexport const kSender = Symbol('kSender')\nconst kStopPropagationPatched = Symbol('kStopPropagationPatched')\nconst KOnStopPropagation = Symbol('KOnStopPropagation')\n\nexport class WebSocketHandler {\n  private readonly __kind: HandlerKind\n\n  public id: string\n  public callFrame?: string\n\n  protected [kEmitter]: Emitter<WebSocketHandlerEventMap>\n\n  constructor(private readonly url: Path) {\n    this.id = createRequestId()\n\n    this[kEmitter] = new Emitter()\n    this.callFrame = getCallFrame(new Error())\n    this.__kind = 'EventHandler'\n  }\n\n  public parse(args: {\n    event: MessageEvent<WebSocketConnectionData>\n  }): WebSocketHandlerParsedResult {\n    const connection = args.event.data\n    const match = matchRequestUrl(connection.client.url, this.url)\n\n    return {\n      match,\n    }\n  }\n\n  public predicate(args: {\n    event: MessageEvent<WebSocketConnectionData>\n    parsedResult: WebSocketHandlerParsedResult\n  }): boolean {\n    return args.parsedResult.match.matches\n  }\n\n  async [kDispatchEvent](\n    event: MessageEvent<WebSocketConnectionData>,\n  ): Promise<void> {\n    const parsedResult = this.parse({ event })\n    const connection = event.data\n\n    const resolvedConnection: WebSocketHandlerConnection = {\n      ...connection,\n      params: parsedResult.match.params || {},\n    }\n\n    // Support `event.stopPropagation()` for various client/server events.\n    connection.client.addEventListener(\n      'message',\n      createStopPropagationListener(this),\n    )\n    connection.client.addEventListener(\n      'close',\n      createStopPropagationListener(this),\n    )\n\n    connection.server.addEventListener(\n      'open',\n      createStopPropagationListener(this),\n    )\n    connection.server.addEventListener(\n      'message',\n      createStopPropagationListener(this),\n    )\n    connection.server.addEventListener(\n      'error',\n      createStopPropagationListener(this),\n    )\n    connection.server.addEventListener(\n      'close',\n      createStopPropagationListener(this),\n    )\n\n    // Emit the connection event on the handler.\n    // This is what the developer adds listeners for.\n    this[kEmitter].emit('connection', resolvedConnection)\n  }\n}\n\nfunction createStopPropagationListener(handler: WebSocketHandler) {\n  return function stopPropagationListener(event: Event) {\n    const propagationStoppedAt = Reflect.get(event, 'kPropagationStoppedAt') as\n      | string\n      | undefined\n\n    if (propagationStoppedAt && handler.id !== propagationStoppedAt) {\n      event.stopImmediatePropagation()\n      return\n    }\n\n    Object.defineProperty(event, KOnStopPropagation, {\n      value(this: WebSocketHandler) {\n        Object.defineProperty(event, 'kPropagationStoppedAt', {\n          value: handler.id,\n        })\n      },\n      configurable: true,\n    })\n\n    // Since the same event instance is shared between all client/server objects,\n    // make sure to patch its `stopPropagation` method only once.\n    if (!Reflect.get(event, kStopPropagationPatched)) {\n      event.stopPropagation = new Proxy(event.stopPropagation, {\n        apply: (target, thisArg, args) => {\n          Reflect.get(event, KOnStopPropagation)?.call(handler)\n          return Reflect.apply(target, thisArg, args)\n        },\n      })\n\n      Object.defineProperty(event, kStopPropagationPatched, {\n        value: true,\n        // If something else attempts to redefine this, throw.\n        configurable: false,\n      })\n    }\n  }\n}\n"],"mappings":"AAAA,SAAS,eAAe;AACxB,SAAS,uBAAuB;AAEhC;AAAA,EAIE;AAAA,OACK;AACP,SAAS,oBAAoB;AAetB,MAAM,WAAW,OAAO,UAAU;AAClC,MAAM,iBAAiB,OAAO,gBAAgB;AAC9C,MAAM,UAAU,OAAO,SAAS;AACvC,MAAM,0BAA0B,OAAO,yBAAyB;AAChE,MAAM,qBAAqB,OAAO,oBAAoB;AAE/C,MAAM,iBAAiB;AAAA,EAQ5B,YAA6B,KAAW;AAAX;AAC3B,SAAK,KAAK,gBAAgB;AAE1B,SAAK,QAAQ,IAAI,IAAI,QAAQ;AAC7B,SAAK,YAAY,aAAa,IAAI,MAAM,CAAC;AACzC,SAAK,SAAS;AAAA,EAChB;AAAA,EAbiB;AAAA,EAEV;AAAA,EACA;AAAA,EAEP,CAAW,QAAQ;AAAA,EAUZ,MAAM,MAEoB;AAC/B,UAAM,aAAa,KAAK,MAAM;AAC9B,UAAM,QAAQ,gBAAgB,WAAW,OAAO,KAAK,KAAK,GAAG;AAE7D,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EAEO,UAAU,MAGL;AACV,WAAO,KAAK,aAAa,MAAM;AAAA,EACjC;AAAA,EAEA,OAAO,cAAc,EACnB,OACe;AACf,UAAM,eAAe,KAAK,MAAM,EAAE,MAAM,CAAC;AACzC,UAAM,aAAa,MAAM;AAEzB,UAAM,qBAAiD;AAAA,MACrD,GAAG;AAAA,MACH,QAAQ,aAAa,MAAM,UAAU,CAAC;AAAA,IACxC;AAGA,eAAW,OAAO;AAAA,MAChB;AAAA,MACA,8BAA8B,IAAI;AAAA,IACpC;AACA,eAAW,OAAO;AAAA,MAChB;AAAA,MACA,8BAA8B,IAAI;AAAA,IACpC;AAEA,eAAW,OAAO;AAAA,MAChB;AAAA,MACA,8BAA8B,IAAI;AAAA,IACpC;AACA,eAAW,OAAO;AAAA,MAChB;AAAA,MACA,8BAA8B,IAAI;AAAA,IACpC;AACA,eAAW,OAAO;AAAA,MAChB;AAAA,MACA,8BAA8B,IAAI;AAAA,IACpC;AACA,eAAW,OAAO;AAAA,MAChB;AAAA,MACA,8BAA8B,IAAI;AAAA,IACpC;AAIA,SAAK,QAAQ,EAAE,KAAK,cAAc,kBAAkB;AAAA,EACtD;AACF;AAEA,SAAS,8BAA8B,SAA2B;AAChE,SAAO,SAAS,wBAAwB,OAAc;AACpD,UAAM,uBAAuB,QAAQ,IAAI,OAAO,uBAAuB;AAIvE,QAAI,wBAAwB,QAAQ,OAAO,sBAAsB;AAC/D,YAAM,yBAAyB;AAC/B;AAAA,IACF;AAEA,WAAO,eAAe,OAAO,oBAAoB;AAAA,MAC/C,QAA8B;AAC5B,eAAO,eAAe,OAAO,yBAAyB;AAAA,UACpD,OAAO,QAAQ;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AAID,QAAI,CAAC,QAAQ,IAAI,OAAO,uBAAuB,GAAG;AAChD,YAAM,kBAAkB,IAAI,MAAM,MAAM,iBAAiB;AAAA,QACvD,OAAO,CAAC,QAAQ,SAAS,SAAS;AAChC,kBAAQ,IAAI,OAAO,kBAAkB,GAAG,KAAK,OAAO;AACpD,iBAAO,QAAQ,MAAM,QAAQ,SAAS,IAAI;AAAA,QAC5C;AAAA,MACF,CAAC;AAED,aAAO,eAAe,OAAO,yBAAyB;AAAA,QACpD,OAAO;AAAA;AAAA,QAEP,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}