{
  "version": 3,
  "sources": ["../src/index.ts", "../src/lib/read-stream.ts", "../src/lib/request-listener.ts"],
  "sourcesContent": ["export { type ClientAddress, type ErrorHandler, type FetchHandler } from './lib/fetch-handler.ts'\nexport {\n  type RequestListenerOptions,\n  createRequestListener,\n  type RequestOptions,\n  createRequest,\n  createHeaders,\n  sendResponse,\n} from './lib/request-listener.ts'\n", "export async function* readStream(stream: ReadableStream<Uint8Array>): AsyncIterable<Uint8Array> {\n  let reader = stream.getReader()\n\n  try {\n    while (true) {\n      let result = await reader.read()\n      if (result.done) break\n      yield result.value\n    }\n  } finally {\n    reader.releaseLock()\n  }\n}\n", "import type * as http from 'node:http'\nimport type * as http2 from 'node:http2'\n\nimport type { ClientAddress, ErrorHandler, FetchHandler } from './fetch-handler.ts'\nimport { readStream } from './read-stream.ts'\n\nexport interface RequestListenerOptions {\n  /**\n   * Overrides the host portion of the incoming request URL. By default the request URL host is\n   * derived from the HTTP `Host` header.\n   *\n   * For example, if you have a `$HOST` environment variable that contains the hostname of your\n   * server, you can use it to set the host of all incoming request URLs like so:\n   *\n   * ```ts\n   * createRequestListener(handler, { host: process.env.HOST })\n   * ```\n   */\n  host?: string\n  /**\n   * An error handler that determines the response when the request handler throws an error. By\n   * default a 500 Internal Server Error response will be sent.\n   */\n  onError?: ErrorHandler\n  /**\n   * Overrides the protocol of the incoming request URL. By default the request URL protocol is\n   * derived from the connection protocol. So e.g. when serving over HTTPS (using\n   * `https.createServer()`), the request URL will begin with `https:`.\n   */\n  protocol?: string\n}\n\n/**\n * Wraps a fetch handler in a Node.js request listener that can be used with:\n *\n * - [`http.createServer()`](https://nodejs.org/api/http.html#httpcreateserveroptions-requestlistener)\n * - [`https.createServer()`](https://nodejs.org/api/https.html#httpscreateserveroptions-requestlistener)\n * - [`http2.createServer()`](https://nodejs.org/api/http2.html#http2createserveroptions-onrequesthandler)\n * - [`http2.createSecureServer()`](https://nodejs.org/api/http2.html#http2createsecureserveroptions-onrequesthandler)\n *\n * Example:\n *\n * ```ts\n * import * as http from 'node:http';\n * import { createRequestListener } from '@remix-run/node-fetch-server';\n *\n * async function handler(request) {\n *   return new Response('Hello, world!');\n * }\n *\n * let server = http.createServer(\n *   createRequestListener(handler)\n * );\n *\n * server.listen(3000);\n * ```\n *\n * @param handler The fetch handler to use for processing incoming requests.\n * @param options Request listener options.\n * @returns A Node.js request listener function.\n */\nexport function createRequestListener(\n  handler: FetchHandler,\n  options?: RequestListenerOptions,\n): http.RequestListener {\n  let onError = options?.onError ?? defaultErrorHandler\n\n  return async (req, res) => {\n    let request = createRequest(req, res, options)\n    let client = {\n      address: req.socket.remoteAddress!,\n      family: req.socket.remoteFamily! as ClientAddress['family'],\n      port: req.socket.remotePort!,\n    }\n\n    let response: Response\n    try {\n      response = await handler(request, client)\n    } catch (error) {\n      try {\n        response = (await onError(error)) ?? internalServerError()\n      } catch (error) {\n        console.error(`There was an error in the error handler: ${error}`)\n        response = internalServerError()\n      }\n    }\n\n    await sendResponse(res, response)\n  }\n}\n\nfunction defaultErrorHandler(error: unknown): Response {\n  console.error(error)\n  return internalServerError()\n}\n\nfunction internalServerError(): Response {\n  return new Response(\n    // \"Internal Server Error\"\n    new Uint8Array([\n      73, 110, 116, 101, 114, 110, 97, 108, 32, 83, 101, 114, 118, 101, 114, 32, 69, 114, 114, 111,\n      114,\n    ]),\n    {\n      status: 500,\n      headers: {\n        'Content-Type': 'text/plain',\n      },\n    },\n  )\n}\n\nexport type RequestOptions = Omit<RequestListenerOptions, 'onError'>\n\n/**\n * Creates a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object from\n *\n * - a [`http.IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage)/[`http.ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse) pair\n * - a [`http2.Http2ServerRequest`](https://nodejs.org/api/http2.html#class-http2http2serverrequest)/[`http2.Http2ServerResponse`](https://nodejs.org/api/http2.html#class-http2http2serverresponse) pair\n *\n * @param req The incoming request object.\n * @param res The server response object.\n * @param options\n * @returns A request object.\n */\nexport function createRequest(\n  req: http.IncomingMessage | http2.Http2ServerRequest,\n  res: http.ServerResponse | http2.Http2ServerResponse,\n  options?: RequestOptions,\n): Request {\n  let controller: AbortController | null = new AbortController()\n\n  // Abort once we can no longer write a response if we have\n  // not yet sent a response (i.e., `close` without `finish`)\n  // `finish` -> done rendering the response\n  // `close` -> response can no longer be written to\n  res.on('close', () => controller?.abort())\n  res.on('finish', () => (controller = null))\n\n  let method = req.method ?? 'GET'\n  let headers = createHeaders(req)\n\n  let protocol =\n    options?.protocol ?? ('encrypted' in req.socket && req.socket.encrypted ? 'https:' : 'http:')\n  let host = options?.host ?? headers.get('Host') ?? 'localhost'\n  let url = new URL(req.url!, `${protocol}//${host}`)\n\n  let init: RequestInit = { method, headers, signal: controller.signal }\n\n  if (method !== 'GET' && method !== 'HEAD') {\n    init.body = new ReadableStream({\n      start(controller) {\n        req.on('data', (chunk) => {\n          controller.enqueue(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength))\n        })\n        req.on('end', () => {\n          controller.close()\n        })\n      },\n    })\n\n    // init.duplex = 'half' must be set when body is a ReadableStream, and Node follows the spec.\n    // However, this property is not defined in the TypeScript types for RequestInit, so we have\n    // to cast it here in order to set it without a type error.\n    // See https://fetch.spec.whatwg.org/#dom-requestinit-duplex\n    ;(init as { duplex: 'half' }).duplex = 'half'\n  }\n\n  return new Request(url, init)\n}\n\n/**\n * Creates a [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) object from the headers in a Node.js\n * [`http.IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage)/[`http2.Http2ServerRequest`](https://nodejs.org/api/http2.html#class-http2http2serverrequest).\n *\n * @param req The incoming request object.\n * @returns A headers object.\n */\nexport function createHeaders(req: http.IncomingMessage | http2.Http2ServerRequest): Headers {\n  let headers = new Headers()\n\n  let rawHeaders = req.rawHeaders\n  for (let i = 0; i < rawHeaders.length; i += 2) {\n    if (rawHeaders[i].startsWith(':')) continue\n    headers.append(rawHeaders[i], rawHeaders[i + 1])\n  }\n\n  return headers\n}\n\n/**\n * Sends a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) to the client using a Node.js\n * [`http.ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse)/[`http2.Http2ServerResponse`](https://nodejs.org/api/http2.html#class-http2http2serverresponse)\n * object.\n *\n * @param res The server response object.\n * @param response The response to send.\n */\nexport async function sendResponse(\n  res: http.ServerResponse | http2.Http2ServerResponse,\n  response: Response,\n): Promise<void> {\n  // Iterate over response.headers so we are sure to send multiple Set-Cookie headers correctly.\n  // These would incorrectly be merged into a single header if we tried to use\n  // `Object.fromEntries(response.headers.entries())`.\n  let headers: Record<string, string | string[]> = {}\n  for (let [key, value] of response.headers) {\n    if (key in headers) {\n      if (Array.isArray(headers[key])) {\n        headers[key].push(value)\n      } else {\n        headers[key] = [headers[key] as string, value]\n      }\n    } else {\n      headers[key] = value\n    }\n  }\n\n  if (res.req.httpVersionMajor === 1) {\n    res.writeHead(response.status, response.statusText, headers)\n  } else {\n    // HTTP/2 doesn't support status messages\n    // https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.4\n    //\n    // HTTP2 `res.writeHead()` will safely ignore the statusText parameter, but\n    // it will emit a warning which we want to avoid.\n    // https://nodejs.org/docs/latest-v22.x/api/http2.html#responsewriteheadstatuscode-statusmessage-headers\n    res.writeHead(response.status, headers)\n  }\n\n  if (response.body != null && res.req.method !== 'HEAD') {\n    for await (let chunk of readStream(response.body)) {\n      // @ts-expect-error - Node typings for http2 require a 2nd parameter to write but it's optional\n      if (res.write(chunk) === false) {\n        await new Promise<void>((resolve) => {\n          res.once('drain', resolve)\n        })\n      }\n    }\n  }\n\n  res.end()\n}\n"],
  "mappings": "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",
  "names": ["error", "controller"]
}
