{"version":3,"file":"node-http-DP_4zoM3.mjs","names":[],"sources":["../src/tako/node-http.ts"],"sourcesContent":["/**\n * Shared helpers for the Node.js HTTP entrypoints (`node-server` and\n * `node-dev`): bridge `node:http` request/response objects to the Fetch\n * API `Request`/`Response` the Tako runtime expects.\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { Readable } from \"node:stream\";\n\nexport function incomingMessageToRequest(req: IncomingMessage): Request {\n  const url = new URL(req.url || \"/\", `http://${req.headers.host || \"localhost\"}`);\n  const method = req.method || \"GET\";\n  const headers = new Headers();\n  for (const [key, value] of Object.entries(req.headers)) {\n    if (value === undefined) continue;\n    if (Array.isArray(value)) {\n      for (const v of value) headers.append(key, v);\n    } else {\n      headers.set(key, value);\n    }\n  }\n\n  const hasBody = method !== \"GET\" && method !== \"HEAD\";\n  const body = hasBody\n    ? new ReadableStream({\n        start(controller) {\n          req.on(\"data\", (chunk: Buffer) => controller.enqueue(chunk));\n          req.on(\"end\", () => controller.close());\n          req.on(\"error\", (err) => controller.error(err));\n        },\n      })\n    : null;\n\n  return new Request(url.href, { method, headers, body, duplex: \"half\" } as RequestInit);\n}\n\nexport async function writeResponse(webResponse: Response, res: ServerResponse): Promise<void> {\n  const headers: Record<string, string | string[]> = {};\n  webResponse.headers.forEach((value, key) => {\n    const existing = headers[key];\n    if (existing !== undefined) {\n      headers[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];\n    } else {\n      headers[key] = value;\n    }\n  });\n  res.writeHead(webResponse.status, headers);\n\n  if (!webResponse.body) {\n    res.end();\n    return;\n  }\n\n  const nodeStream = Readable.fromWeb(\n    webResponse.body as unknown as import(\"node:stream/web\").ReadableStream,\n  );\n  nodeStream.pipe(res);\n  await new Promise<void>((resolve, reject) => {\n    nodeStream.on(\"end\", resolve);\n    nodeStream.on(\"error\", reject);\n  });\n}\n\n/** Start a Node http.Server wired to the given fetch-style handler. */\nexport function startNodeServer(\n  host: string,\n  port: number,\n  handleRequest: (req: Request) => Promise<Response>,\n): Promise<{ actualPort: number; close: () => void }> {\n  return new Promise((resolve) => {\n    const server = createServer(async (req, res) => {\n      try {\n        const request = incomingMessageToRequest(req);\n        const response = await handleRequest(request);\n        await writeResponse(response, res);\n      } catch (err) {\n        console.error(\"Error handling request:\", err);\n        if (!res.headersSent) {\n          res.writeHead(500, { \"Content-Type\": \"application/json\" });\n        }\n        res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n      }\n    });\n\n    server.listen(port, host, () => {\n      const addr = server.address();\n      const actualPort = typeof addr === \"object\" && addr ? addr.port : port;\n      resolve({ actualPort, close: () => server.close() });\n    });\n  });\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,yBAAyB,KAA+B;CACtE,MAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,QAAQ,cAAc;CAChF,MAAM,SAAS,IAAI,UAAU;CAC7B,MAAM,UAAU,IAAI,SAAS;CAC7B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,QAAQ,EAAE;EACtD,IAAI,UAAU,QAAW;EACzB,IAAI,MAAM,QAAQ,MAAM,EACtB,KAAK,MAAM,KAAK,OAAO,QAAQ,OAAO,KAAK,EAAE;OAE7C,QAAQ,IAAI,KAAK,MAAM;;CAK3B,MAAM,OADU,WAAW,SAAS,WAAW,SAE3C,IAAI,eAAe,EACjB,MAAM,YAAY;EAChB,IAAI,GAAG,SAAS,UAAkB,WAAW,QAAQ,MAAM,CAAC;EAC5D,IAAI,GAAG,aAAa,WAAW,OAAO,CAAC;EACvC,IAAI,GAAG,UAAU,QAAQ,WAAW,MAAM,IAAI,CAAC;IAElD,CAAC,GACF;CAEJ,OAAO,IAAI,QAAQ,IAAI,MAAM;EAAE;EAAQ;EAAS;EAAM,QAAQ;EAAQ,CAAgB;;AAGxF,eAAsB,cAAc,aAAuB,KAAoC;CAC7F,MAAM,UAA6C,EAAE;CACrD,YAAY,QAAQ,SAAS,OAAO,QAAQ;EAC1C,MAAM,WAAW,QAAQ;EACzB,IAAI,aAAa,QACf,QAAQ,OAAO,MAAM,QAAQ,SAAS,GAAG,CAAC,GAAG,UAAU,MAAM,GAAG,CAAC,UAAU,MAAM;OAEjF,QAAQ,OAAO;GAEjB;CACF,IAAI,UAAU,YAAY,QAAQ,QAAQ;CAE1C,IAAI,CAAC,YAAY,MAAM;EACrB,IAAI,KAAK;EACT;;CAGF,MAAM,aAAa,SAAS,QAC1B,YAAY,KACb;CACD,WAAW,KAAK,IAAI;CACpB,MAAM,IAAI,SAAe,SAAS,WAAW;EAC3C,WAAW,GAAG,OAAO,QAAQ;EAC7B,WAAW,GAAG,SAAS,OAAO;GAC9B;;;AAIJ,SAAgB,gBACd,MACA,MACA,eACoD;CACpD,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,SAAS,aAAa,OAAO,KAAK,QAAQ;GAC9C,IAAI;IAGF,MAAM,cAAc,MADG,cADP,yBAAyB,IACG,CAAC,EACf,IAAI;YAC3B,KAAK;IACZ,QAAQ,MAAM,2BAA2B,IAAI;IAC7C,IAAI,CAAC,IAAI,aACP,IAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;IAE5D,IAAI,IAAI,KAAK,UAAU,EAAE,OAAO,yBAAyB,CAAC,CAAC;;IAE7D;EAEF,OAAO,OAAO,MAAM,YAAY;GAC9B,MAAM,OAAO,OAAO,SAAS;GAE7B,QAAQ;IAAE,YADS,OAAO,SAAS,YAAY,OAAO,KAAK,OAAO;IAC5C,aAAa,OAAO,OAAO;IAAE,CAAC;IACpD;GACF"}