{"version":3,"file":"getRawRequest-B9kRTvjs.cjs","names":["request: Request","source: RequestControllerSource","DeferredPromise","#handled","symbol","#resolveProperty","bodyInit: { body?: BodyInit | null }","#setInternalProperty","authority: string"],"sources":["../../src/InterceptorError.ts","../../src/RequestController.ts","../../src/utils/canParseUrl.ts","../../src/utils/getValueBySymbol.ts","../../src/utils/fetchUtils.ts","../../src/getRawRequest.ts"],"sourcesContent":["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","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","/**\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\ninterface UndiciRequestState extends RequestInit {}\n\ninterface FetchRequestInit extends Omit<RequestInit, 'mode'> {\n  mode?: RequestMode | 'websocket' | 'webtransport'\n  duplex?: 'half' | 'full'\n}\n\nexport class FetchRequest extends Request {\n  static #resolveProperty<T extends keyof FetchRequestInit & keyof Request>(\n    input: RequestInfo | URL,\n    init: FetchRequestInit = {},\n    key: T\n  ): FetchRequestInit[T] {\n    return init[key] ?? (input instanceof Request ? input[key] : undefined)\n  }\n\n  /**\n   * Check if the given request method is configurable.\n   * @see https://fetch.spec.whatwg.org/#methods\n   */\n  static isConfigurableMethod(method: string): boolean {\n    return method !== 'CONNECT' && method !== 'TRACE' && method !== 'TRACK'\n  }\n\n  static isMethodWithBody(method: string): boolean {\n    return (\n      method !== 'HEAD' &&\n      method !== 'GET' &&\n      FetchRequest.isConfigurableMethod(method)\n    )\n  }\n\n  /**\n   * Check if the given request `mode` is configurable.\n   * @see https://fetch.spec.whatwg.org/#concept-request-mode\n   */\n  static isConfigurableMode(mode: string): boolean {\n    return (\n      mode !== 'navigate' && mode !== 'websocket' && mode !== 'webtransport'\n    )\n  }\n\n  constructor(input: URL | RequestInfo, init?: FetchRequestInit) {\n    const method = FetchRequest.#resolveProperty(input, init, 'method') || 'GET'\n    const safeMethod = FetchRequest.isConfigurableMethod(method)\n      ? method\n      : 'GET'\n\n    const hasExplicitBody = init != null && 'body' in init\n\n    /**\n     * Only include `body` in the super init when it needs to be overridden.\n     * When `input` is a Request and no explicit body is in `init`, let the\n     * Request constructor handle body transfer naturally so it properly\n     * marks the original request's body as consumed (bodyUsed = true).\n     */\n    const bodyInit: { body?: BodyInit | null } = !FetchRequest.isMethodWithBody(\n      method\n    )\n      ? { body: undefined }\n      : hasExplicitBody\n        ? { body: init.body }\n        : {}\n\n    const mode =\n      (FetchRequest.#resolveProperty(input, init, 'mode') as RequestMode) ??\n      undefined\n    const safeMode = FetchRequest.isConfigurableMode(mode) ? mode : undefined\n\n    super(input, {\n      ...(init || {}),\n      method: safeMethod,\n      mode: safeMode,\n      // @ts-expect-error Untyped Node.js property.\n      duplex:\n        init?.duplex ??\n        (FetchRequest.isMethodWithBody(method) ? 'half' : undefined),\n      ...bodyInit,\n    })\n\n    if (method !== safeMethod) {\n      this.#setInternalProperty('method', method)\n    }\n\n    if (method === 'CONNECT') {\n      const url = new URL(input instanceof Request ? input.url : input)\n\n      let authority: string\n\n      /**\n       * @note Node.js has a bug parsing raw CONNECT requests URLs like\n       * \"http://127.0.0.1:1337/localhost:80\". It would treat \"localhost:\" as a protocol.\n       */\n      if (url.protocol === 'localhost:') {\n        authority = url.href\n      } else {\n        authority = url.pathname.replace(/^\\/+/, '')\n      }\n\n      /**\n       * @note Define \"url\" as a getter because Undici uses their own\n       * logic to resolve the \"request.url\" property. Simply reassigning\n       * its value doesn't do anything. This is a destructive action\n       * but it's safe because \"CONNECT\" requests are forbidden per fetch.\n       */\n      Object.defineProperty(this, 'url', {\n        get: () => authority,\n        enumerable: true,\n        configurable: true,\n      })\n    }\n\n    if (mode != null && mode !== safeMode) {\n      this.#setInternalProperty('mode', mode)\n    }\n  }\n\n  #setInternalProperty<T extends keyof Request>(\n    key: T,\n    value: Request[T]\n  ): void {\n    const internalState = getValueBySymbol<UndiciRequestState>('state', this)\n\n    if (internalState) {\n      Reflect.set(internalState, key, value)\n    } else {\n      Object.defineProperty(this, key, {\n        value,\n        enumerable: true,\n        configurable: true,\n        writable: false,\n      })\n    }\n  }\n}\n\nexport interface FetchResponseInit extends ResponseInit {\n  url?: string\n}\n\ninterface UndiciResponseState {\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<UndiciResponseState>('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<UndiciResponseState>('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":"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"}