{"version":3,"sources":["../../src/glossary.ts","../../src/RequestController.ts","../../src/InterceptorError.ts","../../src/utils/canParseUrl.ts","../../src/utils/getValueBySymbol.ts","../../src/utils/fetchUtils.ts","../../src/getRawRequest.ts"],"sourcesContent":["import type { RequestController } from './RequestController'\n\nexport const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')\n\n/**\n * @note Export `RequestController` as a type only.\n * It's never meant to be created in the userland.\n */\nexport type { RequestController }\n\nexport type RequestCredentials = 'omit' | 'include' | 'same-origin'\n\nexport type HttpRequestEventMap = {\n  request: [\n    args: {\n      request: Request\n      requestId: string\n      controller: RequestController\n    }\n  ]\n  response: [\n    args: {\n      response: Response\n      isMockedResponse: boolean\n      request: Request\n      requestId: string\n    }\n  ]\n  unhandledException: [\n    args: {\n      error: unknown\n      request: Request\n      requestId: string\n      controller: RequestController\n    }\n  ]\n}\n","import { DeferredPromise } from '@open-draft/deferred-promise'\nimport { invariant } from 'outvariant'\nimport { InterceptorError } from './InterceptorError'\n\nexport interface RequestControllerSource {\n  passthrough(): void\n  respondWith(response: Response): void\n  errorWith(reason?: unknown): void\n}\n\nexport class RequestController {\n  static PENDING = 0 as const\n  static PASSTHROUGH = 1 as const\n  static RESPONSE = 2 as const\n  static ERROR = 3 as const\n\n  public readyState: number\n\n  /**\n   * A Promise that resolves when this controller handles a request.\n   * See `controller.readyState` for more information on the handling result.\n   */\n  public handled: Promise<void>\n\n  constructor(\n    protected readonly request: Request,\n    protected readonly source: RequestControllerSource\n  ) {\n    this.readyState = RequestController.PENDING\n    this.handled = new DeferredPromise<void>()\n  }\n\n  get #handled() {\n    return this.handled as DeferredPromise<void>\n  }\n\n  /**\n   * Perform this request as-is.\n   */\n  public async passthrough(): Promise<void> {\n    invariant.as(\n      InterceptorError,\n      this.readyState === RequestController.PENDING,\n      'Failed to passthrough the \"%s %s\" request: the request has already been handled',\n      this.request.method,\n      this.request.url\n    )\n\n    this.readyState = RequestController.PASSTHROUGH\n    await this.source.passthrough()\n    this.#handled.resolve()\n  }\n\n  /**\n   * Respond to this request with the given `Response` instance.\n   *\n   * @example\n   * controller.respondWith(new Response())\n   * controller.respondWith(Response.json({ id }))\n   * controller.respondWith(Response.error())\n   */\n  public respondWith(response: Response): void {\n    invariant.as(\n      InterceptorError,\n      this.readyState === RequestController.PENDING,\n      'Failed to respond to the \"%s %s\" request with \"%d %s\": the request has already been handled (%d)',\n      this.request.method,\n      this.request.url,\n      response.status,\n      response.statusText || 'OK',\n      this.readyState\n    )\n\n    this.readyState = RequestController.RESPONSE\n    this.#handled.resolve()\n\n    /**\n     * @note Although `source.respondWith()` is potentially asynchronous,\n     * do NOT await it for backward-compatibility. Awaiting it will short-circuit\n     * the request listener invocation as soon as a listener responds to a request.\n     * Ideally, that's what we want, but that's not what we promise the user.\n     */\n    this.source.respondWith(response)\n  }\n\n  /**\n   * Error this request with the given reason.\n   *\n   * @example\n   * controller.errorWith()\n   * controller.errorWith(new Error('Oops!'))\n   * controller.errorWith({ message: 'Oops!'})\n   */\n  public errorWith(reason?: unknown): void {\n    invariant.as(\n      InterceptorError,\n      this.readyState === RequestController.PENDING,\n      'Failed to error the \"%s %s\" request with \"%s\": the request has already been handled (%d)',\n      this.request.method,\n      this.request.url,\n      reason?.toString(),\n      this.readyState\n    )\n\n    this.readyState = RequestController.ERROR\n    this.source.errorWith(reason)\n    this.#handled.resolve()\n  }\n}\n","export class InterceptorError extends Error {\n  constructor(message?: string) {\n    super(message)\n    this.name = 'InterceptorError'\n    Object.setPrototypeOf(this, InterceptorError.prototype)\n  }\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n  try {\n    new URL(url)\n    return true\n  } catch (_error) {\n    return false\n  }\n}\n","/**\n * Returns the value behind the symbol with the given name.\n */\nexport function getValueBySymbol<T>(\n  symbolName: string,\n  source: object\n): T | undefined {\n  const ownSymbols = Object.getOwnPropertySymbols(source)\n\n  const symbol = ownSymbols.find((symbol) => {\n    return symbol.description === symbolName\n  })\n\n  if (symbol) {\n    return Reflect.get(source, symbol)\n  }\n\n  return\n}\n","import { canParseUrl } from './canParseUrl'\nimport { getValueBySymbol } from './getValueBySymbol'\n\nexport interface FetchResponseInit extends ResponseInit {\n  url?: string\n}\n\ninterface UndiciFetchInternalState {\n  aborted: boolean\n  rangeRequested: boolean\n  timingAllowPassed: boolean\n  requestIncludesCredentials: boolean\n  type: ResponseType\n  status: number\n  statusText: string\n  timingInfo: unknown\n  cacheState: unknown\n  headersList: Record<symbol, Map<string, unknown>>\n  urlList: Array<URL>\n  body?: {\n    stream: ReadableStream\n    source: unknown\n    length: number\n  }\n}\n\nexport class FetchResponse extends Response {\n  /**\n   * Response status codes for responses that cannot have body.\n   * @see https://fetch.spec.whatwg.org/#statuses\n   */\n  static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n  static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n  static isConfigurableStatusCode(status: number): boolean {\n    return status >= 200 && status <= 599\n  }\n\n  static isRedirectResponse(status: number): boolean {\n    return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n  }\n\n  /**\n   * Returns a boolean indicating whether the given response status\n   * code represents a response that can have a body.\n   */\n  static isResponseWithBody(status: number): boolean {\n    return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n  }\n\n  static setUrl(url: string | undefined, response: Response): void {\n    if (!url || url === 'about:' || !canParseUrl(url)) {\n      return\n    }\n\n    const state = getValueBySymbol<UndiciFetchInternalState>('state', response)\n\n    if (state) {\n      // In Undici, push the URL to the internal list of URLs.\n      // This will respect the `response.url` getter logic correctly.\n      state.urlList.push(new URL(url))\n    } else {\n      // In other libraries, redefine the `url` property directly.\n      Object.defineProperty(response, 'url', {\n        value: url,\n        enumerable: true,\n        configurable: true,\n        writable: false,\n      })\n    }\n  }\n\n  /**\n   * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n   */\n  static parseRawHeaders(rawHeaders: Array<string>): Headers {\n    const headers = new Headers()\n    for (let line = 0; line < rawHeaders.length; line += 2) {\n      headers.append(rawHeaders[line], rawHeaders[line + 1])\n    }\n    return headers\n  }\n\n  constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n    const status = init.status ?? 200\n    const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n      ? status\n      : 200\n    const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n    super(finalBody, {\n      status: safeStatus,\n      statusText: init.statusText,\n      headers: init.headers,\n    })\n\n    if (status !== safeStatus) {\n      /**\n       * @note Undici keeps an internal \"Symbol(state)\" that holds\n       * the actual value of response status. Update that in Node.js.\n       */\n      const state = getValueBySymbol<UndiciFetchInternalState>('state', this)\n\n      if (state) {\n        state.status = status\n      } else {\n        Object.defineProperty(this, 'status', {\n          value: status,\n          enumerable: true,\n          configurable: true,\n          writable: false,\n        })\n      }\n    }\n\n    FetchResponse.setUrl(init.url, this)\n  }\n}\n","const kRawRequest = Symbol('kRawRequest')\n\n/**\n * Returns a raw request instance associated with this request.\n *\n * @example\n * interceptor.on('request', ({ request }) => {\n *   const rawRequest = getRawRequest(request)\n *\n *   if (rawRequest instanceof http.ClientRequest) {\n *     console.log(rawRequest.rawHeaders)\n *   }\n * })\n */\nexport function getRawRequest(request: Request): unknown | undefined {\n  return Reflect.get(request, kRawRequest)\n}\n\nexport function setRawRequest(request: Request, rawRequest: unknown): void {\n  Reflect.set(request, kRawRequest, rawRequest)\n}\n"],"mappings":";;;;;;AAEO,IAAM,oBAAmC,OAAO,iBAAiB;;;ACFxE,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;;;ACDnB,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YAAY,SAAkB;AAC5B,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,WAAO,eAAe,MAAM,iBAAiB,SAAS;AAAA,EACxD;AACF;;;ADNA;AAUO,IAAM,qBAAN,MAAwB;AAAA,EAc7B,YACqB,SACA,QACnB;AAFmB;AACA;AAMrB,uBAAI;AAJF,SAAK,aAAa,mBAAkB;AACpC,SAAK,UAAU,IAAI,gBAAsB;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,cAA6B;AACxC,cAAU;AAAA,MACR;AAAA,MACA,KAAK,eAAe,mBAAkB;AAAA,MACtC;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAEA,SAAK,aAAa,mBAAkB;AACpC,UAAM,KAAK,OAAO,YAAY;AAC9B,uBAAK,uBAAS,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUO,YAAY,UAA0B;AAC3C,cAAU;AAAA,MACR;AAAA,MACA,KAAK,eAAe,mBAAkB;AAAA,MACtC;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,MACb,SAAS;AAAA,MACT,SAAS,cAAc;AAAA,MACvB,KAAK;AAAA,IACP;AAEA,SAAK,aAAa,mBAAkB;AACpC,uBAAK,uBAAS,QAAQ;AAQtB,SAAK,OAAO,YAAY,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUO,UAAU,QAAwB;AACvC,cAAU;AAAA,MACR;AAAA,MACA,KAAK,eAAe,mBAAkB;AAAA,MACtC;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,MACb,iCAAQ;AAAA,MACR,KAAK;AAAA,IACP;AAEA,SAAK,aAAa,mBAAkB;AACpC,SAAK,OAAO,UAAU,MAAM;AAC5B,uBAAK,uBAAS,QAAQ;AAAA,EACxB;AACF;AAlGO,IAAM,oBAAN;AAsBD;AAAA,cAAQ,WAAG;AACb,SAAO,KAAK;AACd;AAxBW,kBACJ,UAAU;AADN,kBAEJ,cAAc;AAFV,kBAGJ,WAAW;AAHP,kBAIJ,QAAQ;;;AETV,SAAS,YAAY,KAAsB;AAChD,MAAI;AACF,QAAI,IAAI,GAAG;AACX,WAAO;AAAA,EACT,SAAS,QAAP;AACA,WAAO;AAAA,EACT;AACF;;;ACTO,SAAS,iBACd,YACA,QACe;AACf,QAAM,aAAa,OAAO,sBAAsB,MAAM;AAEtD,QAAM,SAAS,WAAW,KAAK,CAACA,YAAW;AACzC,WAAOA,QAAO,gBAAgB;AAAA,EAChC,CAAC;AAED,MAAI,QAAQ;AACV,WAAO,QAAQ,IAAI,QAAQ,MAAM;AAAA,EACnC;AAEA;AACF;;;ACQO,IAAM,iBAAN,cAA4B,SAAS;AAAA,EAS1C,OAAO,yBAAyB,QAAyB;AACvD,WAAO,UAAU,OAAO,UAAU;AAAA,EACpC;AAAA,EAEA,OAAO,mBAAmB,QAAyB;AACjD,WAAO,eAAc,2BAA2B,SAAS,MAAM;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,QAAyB;AACjD,WAAO,CAAC,eAAc,0BAA0B,SAAS,MAAM;AAAA,EACjE;AAAA,EAEA,OAAO,OAAO,KAAyB,UAA0B;AAC/D,QAAI,CAAC,OAAO,QAAQ,YAAY,CAAC,YAAY,GAAG,GAAG;AACjD;AAAA,IACF;AAEA,UAAM,QAAQ,iBAA2C,SAAS,QAAQ;AAE1E,QAAI,OAAO;AAGT,YAAM,QAAQ,KAAK,IAAI,IAAI,GAAG,CAAC;AAAA,IACjC,OAAO;AAEL,aAAO,eAAe,UAAU,OAAO;AAAA,QACrC,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,gBAAgB,YAAoC;AACzD,UAAM,UAAU,IAAI,QAAQ;AAC5B,aAAS,OAAO,GAAG,OAAO,WAAW,QAAQ,QAAQ,GAAG;AACtD,cAAQ,OAAO,WAAW,IAAI,GAAG,WAAW,OAAO,CAAC,CAAC;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,MAAwB,OAA0B,CAAC,GAAG;AApFpE;AAqFI,UAAM,UAAS,UAAK,WAAL,YAAe;AAC9B,UAAM,aAAa,eAAc,yBAAyB,MAAM,IAC5D,SACA;AACJ,UAAM,YAAY,eAAc,mBAAmB,MAAM,IAAI,OAAO;AAEpE,UAAM,WAAW;AAAA,MACf,QAAQ;AAAA,MACR,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB,CAAC;AAED,QAAI,WAAW,YAAY;AAKzB,YAAM,QAAQ,iBAA2C,SAAS,IAAI;AAEtE,UAAI,OAAO;AACT,cAAM,SAAS;AAAA,MACjB,OAAO;AACL,eAAO,eAAe,MAAM,UAAU;AAAA,UACpC,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,cAAc;AAAA,UACd,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,mBAAc,OAAO,KAAK,KAAK,IAAI;AAAA,EACrC;AACF;AA5FO,IAAM,gBAAN;AAAA;AAAA;AAAA;AAAA;AAAM,cAKK,4BAA4B,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AALzD,cAOK,6BAA6B,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;;;ACjCvE,IAAM,cAAc,OAAO,aAAa;AAcjC,SAAS,cAAc,SAAuC;AACnE,SAAO,QAAQ,IAAI,SAAS,WAAW;AACzC;AAEO,SAAS,cAAc,SAAkB,YAA2B;AACzE,UAAQ,IAAI,SAAS,aAAa,UAAU;AAC9C;","names":["symbol"]}