{"version":3,"sources":["../../../../src/core/experimental/sources/interceptor-source.ts"],"sourcesContent":["import type { Interceptor, RequestController } from '@mswjs/interceptors'\nimport { BatchInterceptor, type HttpRequestEventMap } from '@mswjs/interceptors'\nimport type {\n  WebSocketConnectionData,\n  WebSocketEventMap,\n} from '@mswjs/interceptors/WebSocket'\nimport { NetworkSource } from './network-source'\nimport { InternalError } from '../../utils/internal/devUtils'\nimport { HttpNetworkFrame, ResponseEvent } from '../frames/http-frame'\nimport { WebSocketNetworkFrame } from '../frames/websocket-frame'\nimport { deleteRequestPassthroughHeader } from '../request-utils'\n\nexport interface InterceptorSourceOptions {\n  interceptors: Array<Interceptor<HttpRequestEventMap | WebSocketEventMap>>\n}\n\n/**\n * Create a network source from the given list of interceptors.\n */\nexport class InterceptorSource extends NetworkSource {\n  #interceptor: BatchInterceptor<\n    InterceptorSourceOptions['interceptors'],\n    HttpRequestEventMap | WebSocketEventMap\n  >\n\n  #frames: Map<string, HttpNetworkFrame>\n\n  constructor(options: InterceptorSourceOptions) {\n    super()\n\n    this.#interceptor = new BatchInterceptor({\n      name: 'interceptor-source',\n      interceptors: options.interceptors,\n    })\n    this.#frames = new Map()\n  }\n\n  public enable(): void {\n    this.#interceptor.apply()\n\n    /**\n     * @todo @fixme BatchInterceptor infers event types but not listener types.\n     */\n    this.#interceptor\n      .on('request', this.#handleRequest.bind(this) as any)\n      .on('response', this.#handleResponse.bind(this) as any)\n      .on('connection', this.#handleWebSocketConnection.bind(this) as any)\n  }\n\n  public disable(): void {\n    super.disable()\n    this.#interceptor.dispose()\n\n    /**\n     * @todo We can also abort any pending frames here, given we implement\n     * the `NetworkFrame.abort()` method.\n     */\n    this.#frames.clear()\n  }\n\n  async #handleRequest({\n    requestId,\n    request,\n    controller,\n  }: HttpRequestEventMap['request'][0]): Promise<void> {\n    const httpFrame = new InterceptorHttpNetworkFrame({\n      id: requestId,\n      request,\n      controller,\n    })\n\n    this.#frames.set(requestId, httpFrame)\n    await this.queue(httpFrame)\n  }\n\n  async #handleResponse({\n    requestId,\n    request,\n    response,\n    isMockedResponse,\n  }: HttpRequestEventMap['response'][0]): Promise<void> {\n    const httpFrame = this.#frames.get(requestId)\n    this.#frames.delete(requestId)\n\n    if (httpFrame == null) {\n      return\n    }\n\n    queueMicrotask(() => {\n      httpFrame.events.emit(\n        new ResponseEvent(\n          isMockedResponse ? 'response:mocked' : 'response:bypass',\n          {\n            requestId,\n            request,\n            response,\n          },\n        ),\n      )\n    })\n  }\n\n  async #handleWebSocketConnection(\n    connection: WebSocketEventMap['connection'][0],\n  ): Promise<void> {\n    await this.queue(\n      new InterceptorWebSocketNetworkFrame({\n        connection,\n      }),\n    )\n  }\n}\n\nclass InterceptorHttpNetworkFrame extends HttpNetworkFrame {\n  #controller: RequestController\n\n  constructor(options: {\n    id: string\n    request: Request\n    controller: RequestController\n  }) {\n    super({\n      id: options.id,\n      request: options.request,\n    })\n\n    this.#controller = options.controller\n  }\n\n  public passthrough(): void {\n    deleteRequestPassthroughHeader(this.data.request)\n  }\n\n  public respondWith(response?: Response): void {\n    if (response) {\n      this.#controller.respondWith(response)\n    }\n  }\n\n  public errorWith(reason?: unknown): void {\n    if (reason instanceof Response) {\n      return this.respondWith(reason)\n    }\n\n    if (reason instanceof InternalError) {\n      this.#controller.errorWith(reason)\n    }\n\n    throw reason\n  }\n}\n\nclass InterceptorWebSocketNetworkFrame extends WebSocketNetworkFrame {\n  constructor(args: { connection: WebSocketConnectionData }) {\n    super({ connection: args.connection })\n  }\n\n  public errorWith(reason?: unknown): void {\n    if (reason instanceof Error) {\n      const { client } = this.data.connection\n\n      /**\n       * Use `client.errorWith(reason)` in the future.\n       * @see https://github.com/mswjs/interceptors/issues/747\n       */\n      const errorEvent = new Event('error')\n\n      Object.defineProperty(errorEvent, 'cause', {\n        enumerable: true,\n        configurable: false,\n        value: reason,\n      })\n\n      client.socket.dispatchEvent(errorEvent)\n    }\n  }\n\n  public passthrough() {\n    this.data.connection.server.connect()\n  }\n}\n"],"mappings":"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","names":[]}