{"version":3,"file":"node.cjs","names":["frameworkName: SupportedFrameworkName","chunks: Buffer[]","URL","InngestCommHandler","http","createWebApiCommHandler","handleDurableEndpointProxyRequest","InngestEndpointAdapter","resHeaders: Record<string, string>"],"sources":["../src/node.ts"],"sourcesContent":["import http from \"node:http\";\nimport type { TLSSocket } from \"node:tls\";\nimport { URL } from \"node:url\";\nimport { createWebApiCommHandler } from \"./components/createWebApiCommHandler.ts\";\nimport type { Inngest } from \"./components/Inngest.ts\";\nimport {\n  InngestCommHandler,\n  type ServeHandlerOptions,\n  type SyncHandlerOptions,\n} from \"./components/InngestCommHandler.ts\";\nimport { handleDurableEndpointProxyRequest } from \"./components/InngestDurableEndpointProxy.ts\";\nimport { InngestEndpointAdapter } from \"./components/InngestEndpointAdapter.ts\";\nimport type { RegisterOptions, SupportedFrameworkName } from \"./types.ts\";\n\n/**\n * The name of the framework, used to identify the framework in Inngest\n * dashboards and during testing.\n */\nexport const frameworkName: SupportedFrameworkName = \"nodejs\";\n\n/**\n * Read the incoming message body as text.\n *\n * Collects Buffer chunks and decodes once with `Buffer.concat` so multi-byte\n * UTF-8 characters aren't corrupted when split across chunk boundaries.\n * Reads via `req.on('data'|'end')` so body-replay wrappers — notably\n * `@vercel/node`'s `restoreBody()`, which patches only those two events —\n * deliver the replayed bytes; async-iterator and `readable`-event readers\n * see an empty body under that wrapper.\n */\nexport async function readRequestBody(\n  req: http.IncomingMessage,\n): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const chunks: Buffer[] = [];\n    req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n    req.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\n    req.on(\"error\", reject);\n  });\n}\n\nfunction getURL(req: http.IncomingMessage, hostnameOption?: string): URL {\n  const protocol =\n    (req.headers[\"x-forwarded-proto\"] as string) ||\n    ((req.socket as TLSSocket)?.encrypted ? \"https\" : \"http\");\n  const origin = hostnameOption || `${protocol}://${req.headers.host}`;\n  return new URL(req.url || \"\", origin);\n}\n\nconst commHandler = (options: ServeHandlerOptions | SyncHandlerOptions) => {\n  const handler = new InngestCommHandler({\n    frameworkName,\n    ...options,\n    handler: (req: http.IncomingMessage, res: http.ServerResponse) => {\n      return {\n        body: () => readRequestBody(req),\n        headers: (key) => {\n          return req.headers[key] && Array.isArray(req.headers[key])\n            ? req.headers[key][0]\n            : req.headers[key];\n        },\n        method: () => {\n          if (!req.method) {\n            throw new Error(\n              \"Request method not defined. Potential use outside of context of Server.\",\n            );\n          }\n          return req.method;\n        },\n        url: () => getURL(req, options.serveOrigin),\n        transformResponse: ({ body, status, headers }) => {\n          res.writeHead(status, headers);\n          res.end(body);\n        },\n\n        transformStreamingResponse: async ({ body, headers, status }) => {\n          res.writeHead(status, headers);\n\n          const reader = body.getReader();\n          try {\n            let done = false;\n            while (!done) {\n              const result = await reader.read();\n              done = result.done;\n              if (!done) {\n                res.write(result.value);\n              }\n            }\n            res.end();\n          } catch (error) {\n            if (error instanceof Error) {\n              res.destroy(error);\n            } else {\n              res.destroy(new Error(String(error)));\n            }\n          }\n        },\n      };\n    },\n  });\n\n  return handler;\n};\n\n/**\n * Serve and register any declared functions with Inngest, making them available\n * to be triggered by events.\n *\n * @example Serve Inngest functions on all paths\n * ```ts\n * import { serve } from \"inngest/node\";\n * import { inngest } from \"./src/inngest/client\";\n * import myFn from \"./src/inngest/myFn\"; // Your own function\n *\n * const server = http.createServer(serve({\n *   client: inngest, functions: [myFn]\n * }));\n * server.listen(3000);\n * ```\n *\n * @example Serve Inngest on a specific path\n * ```ts\n * import { serve } from \"inngest/node\";\n * import { inngest } from \"./src/inngest/client\";\n * import myFn from \"./src/inngest/myFn\"; // Your own function\n *\n * const server = http.createServer((req, res) => {\n *   if (req.url.start === '/api/inngest') {\n *     return serve({\n *       client: inngest, functions: [myFn]\n *     })(req, res);\n *   }\n *   // ...\n * });\n * server.listen(3000);\n * ```\n *\n * @public\n */\n// Has explicit return type to avoid JSR-defined \"slow types\"\nexport const serve = (options: ServeHandlerOptions): http.RequestListener => {\n  return commHandler(options).createHandler() as http.RequestListener;\n};\n\n/**\n * EXPERIMENTAL - Create an http server to serve Inngest functions.\n *\n * @example\n * ```ts\n * import { createServer } from \"inngest/node\";\n * import { inngest } from \"./src/inngest/client\";\n * import myFn from \"./src/inngest/myFn\"; // Your own function\n *\n * const server = createServer({\n *   client: inngest, functions: [myFn]\n * });\n * server.listen(3000);\n * ```\n *\n * @public\n */\nexport const createServer = (options: ServeHandlerOptions) => {\n  const server = http.createServer((req, res) => {\n    const url = getURL(req, options.serveOrigin);\n    const pathname = options.servePath || \"/api/inngest\";\n    if (url.pathname === pathname) {\n      return serve(options)(req, res);\n    }\n    res.writeHead(404);\n    res.end();\n  });\n  server.on(\"clientError\", (_err, socket) => {\n    socket.end(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\");\n  });\n  return server;\n};\n\nexport type EndpointHandler = (req: Request) => Promise<Response>;\n\n/**\n * Comm handler for durable endpoints. Uses Web API Request/Response since\n * that's the interface users write against, regardless of the underlying\n * runtime.\n */\nfunction endpointCommHandler(\n  options: RegisterOptions & { client: Inngest.Like },\n  syncOptions?: SyncHandlerOptions,\n): InngestCommHandler {\n  return createWebApiCommHandler(frameworkName, options, syncOptions);\n}\n\n/**\n * Creates a durable endpoint proxy handler for Node.js environments.\n */\nfunction createDurableEndpointProxyHandler(\n  options: InngestEndpointAdapter.ProxyHandlerOptions,\n): http.RequestListener {\n  return async (\n    req: http.IncomingMessage,\n    res: http.ServerResponse,\n  ): Promise<void> => {\n    const url = getURL(req);\n\n    const result = await handleDurableEndpointProxyRequest(\n      options.client as Inngest.Any,\n      {\n        runId: url.searchParams.get(\"runId\"),\n        token: url.searchParams.get(\"token\"),\n        method: req.method || \"GET\",\n      },\n    );\n\n    res.writeHead(result.status, result.headers);\n    res.end(result.body);\n  };\n}\n\n/**\n * In a Node.js environment, create a function that can wrap any endpoint to be\n * able to use steps seamlessly within that API.\n */\nexport const endpointAdapter = InngestEndpointAdapter.create((options) => {\n  return endpointCommHandler(options, options).createSyncHandler();\n}, createDurableEndpointProxyHandler);\n\n/**\n * Bridge a Web API endpoint handler to a Node.js `http.RequestListener`.\n *\n * Converts an incoming `http.IncomingMessage` into a Web API `Request`,\n * invokes the handler, then streams the resulting `Response` back through\n * the Node.js `http.ServerResponse`.\n *\n * Important: uses `value != null` (not `value`) when forwarding headers so\n * that empty-string headers (like `X-Inngest-Signature: \"\"` in dev mode)\n * are preserved. Dropping them breaks `isInngestReq()` detection.\n */\nexport function serveEndpoint(handler: EndpointHandler): http.RequestListener {\n  return async (req: http.IncomingMessage, res: http.ServerResponse) => {\n    const body = await readRequestBody(req);\n\n    const headers = new Headers();\n    for (const [key, value] of Object.entries(req.headers)) {\n      if (value != null) {\n        if (Array.isArray(value)) {\n          for (const v of value) {\n            headers.append(key, v);\n          }\n        } else if (typeof value === \"string\") {\n          headers.set(key, value);\n        }\n      }\n    }\n\n    const url = getURL(req);\n    const webRequest = new Request(url.href, {\n      method: req.method,\n      headers,\n      body: body.length > 0 ? body : undefined,\n    });\n\n    try {\n      const webResponse = await handler(webRequest);\n\n      const resHeaders: Record<string, string> = {};\n      webResponse.headers.forEach((v, k) => {\n        resHeaders[k] = v;\n      });\n      res.writeHead(webResponse.status, resHeaders);\n\n      if (webResponse.body) {\n        const reader = webResponse.body.getReader();\n        while (true) {\n          const { done, value } = await reader.read();\n          if (done) {\n            break;\n          }\n          res.write(value);\n        }\n      }\n      res.end();\n    } catch (err) {\n      if (!res.headersSent) {\n        res.writeHead(500);\n      }\n      res.end(String(err));\n    }\n  };\n}\n\n/**\n * Create an HTTP server that serves a durable endpoint handler.\n *\n * This bridges the Web API `Request`/`Response` interface that Durable\n * Endpoints use with Node.js's `http.Server`.\n */\nexport function createEndpointServer(handler: EndpointHandler): http.Server {\n  const listener = serveEndpoint(handler);\n  const server = http.createServer(listener);\n  server.on(\"clientError\", (_err, socket) => {\n    socket.end(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\");\n  });\n  return server;\n}\n"],"mappings":";;;;;;;;;;;;;;AAkBA,MAAaA,gBAAwC;;;;;;;;;;;AAYrD,eAAsB,gBACpB,KACiB;AACjB,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAMC,SAAmB,EAAE;AAC3B,MAAI,GAAG,SAAS,UAAkB,OAAO,KAAK,MAAM,CAAC;AACrD,MAAI,GAAG,aAAa,QAAQ,OAAO,OAAO,OAAO,CAAC,SAAS,OAAO,CAAC,CAAC;AACpE,MAAI,GAAG,SAAS,OAAO;GACvB;;AAGJ,SAAS,OAAO,KAA2B,gBAA8B;CACvE,MAAM,WACH,IAAI,QAAQ,yBACX,IAAI,QAAsB,YAAY,UAAU;CACpD,MAAM,SAAS,kBAAkB,GAAG,SAAS,KAAK,IAAI,QAAQ;AAC9D,QAAO,IAAIC,aAAI,IAAI,OAAO,IAAI,OAAO;;AAGvC,MAAM,eAAe,YAAsD;AAoDzE,QAnDgB,IAAIC,8CAAmB;EACrC;EACA,GAAG;EACH,UAAU,KAA2B,QAA6B;AAChE,UAAO;IACL,YAAY,gBAAgB,IAAI;IAChC,UAAU,QAAQ;AAChB,YAAO,IAAI,QAAQ,QAAQ,MAAM,QAAQ,IAAI,QAAQ,KAAK,GACtD,IAAI,QAAQ,KAAK,KACjB,IAAI,QAAQ;;IAElB,cAAc;AACZ,SAAI,CAAC,IAAI,OACP,OAAM,IAAI,MACR,0EACD;AAEH,YAAO,IAAI;;IAEb,WAAW,OAAO,KAAK,QAAQ,YAAY;IAC3C,oBAAoB,EAAE,MAAM,QAAQ,cAAc;AAChD,SAAI,UAAU,QAAQ,QAAQ;AAC9B,SAAI,IAAI,KAAK;;IAGf,4BAA4B,OAAO,EAAE,MAAM,SAAS,aAAa;AAC/D,SAAI,UAAU,QAAQ,QAAQ;KAE9B,MAAM,SAAS,KAAK,WAAW;AAC/B,SAAI;MACF,IAAI,OAAO;AACX,aAAO,CAAC,MAAM;OACZ,MAAM,SAAS,MAAM,OAAO,MAAM;AAClC,cAAO,OAAO;AACd,WAAI,CAAC,KACH,KAAI,MAAM,OAAO,MAAM;;AAG3B,UAAI,KAAK;cACF,OAAO;AACd,UAAI,iBAAiB,MACnB,KAAI,QAAQ,MAAM;UAElB,KAAI,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,CAAC;;;IAI5C;;EAEJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCJ,MAAa,SAAS,YAAuD;AAC3E,QAAO,YAAY,QAAQ,CAAC,eAAe;;;;;;;;;;;;;;;;;;;AAoB7C,MAAa,gBAAgB,YAAiC;CAC5D,MAAM,SAASC,kBAAK,cAAc,KAAK,QAAQ;EAC7C,MAAM,MAAM,OAAO,KAAK,QAAQ,YAAY;EAC5C,MAAM,WAAW,QAAQ,aAAa;AACtC,MAAI,IAAI,aAAa,SACnB,QAAO,MAAM,QAAQ,CAAC,KAAK,IAAI;AAEjC,MAAI,UAAU,IAAI;AAClB,MAAI,KAAK;GACT;AACF,QAAO,GAAG,gBAAgB,MAAM,WAAW;AACzC,SAAO,IAAI,mCAAmC;GAC9C;AACF,QAAO;;;;;;;AAUT,SAAS,oBACP,SACA,aACoB;AACpB,QAAOC,wDAAwB,eAAe,SAAS,YAAY;;;;;AAMrE,SAAS,kCACP,SACsB;AACtB,QAAO,OACL,KACA,QACkB;EAClB,MAAM,MAAM,OAAO,IAAI;EAEvB,MAAM,SAAS,MAAMC,sEACnB,QAAQ,QACR;GACE,OAAO,IAAI,aAAa,IAAI,QAAQ;GACpC,OAAO,IAAI,aAAa,IAAI,QAAQ;GACpC,QAAQ,IAAI,UAAU;GACvB,CACF;AAED,MAAI,UAAU,OAAO,QAAQ,OAAO,QAAQ;AAC5C,MAAI,IAAI,OAAO,KAAK;;;;;;;AAQxB,MAAa,kBAAkBC,sDAAuB,QAAQ,YAAY;AACxE,QAAO,oBAAoB,SAAS,QAAQ,CAAC,mBAAmB;GAC/D,kCAAkC;;;;;;;;;;;;AAarC,SAAgB,cAAc,SAAgD;AAC5E,QAAO,OAAO,KAA2B,QAA6B;EACpE,MAAM,OAAO,MAAM,gBAAgB,IAAI;EAEvC,MAAM,UAAU,IAAI,SAAS;AAC7B,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,QAAQ,CACpD,KAAI,SAAS,MACX;OAAI,MAAM,QAAQ,MAAM,CACtB,MAAK,MAAM,KAAK,MACd,SAAQ,OAAO,KAAK,EAAE;YAEf,OAAO,UAAU,SAC1B,SAAQ,IAAI,KAAK,MAAM;;EAK7B,MAAM,MAAM,OAAO,IAAI;EACvB,MAAM,aAAa,IAAI,QAAQ,IAAI,MAAM;GACvC,QAAQ,IAAI;GACZ;GACA,MAAM,KAAK,SAAS,IAAI,OAAO;GAChC,CAAC;AAEF,MAAI;GACF,MAAM,cAAc,MAAM,QAAQ,WAAW;GAE7C,MAAMC,aAAqC,EAAE;AAC7C,eAAY,QAAQ,SAAS,GAAG,MAAM;AACpC,eAAW,KAAK;KAChB;AACF,OAAI,UAAU,YAAY,QAAQ,WAAW;AAE7C,OAAI,YAAY,MAAM;IACpB,MAAM,SAAS,YAAY,KAAK,WAAW;AAC3C,WAAO,MAAM;KACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,SAAI,KACF;AAEF,SAAI,MAAM,MAAM;;;AAGpB,OAAI,KAAK;WACF,KAAK;AACZ,OAAI,CAAC,IAAI,YACP,KAAI,UAAU,IAAI;AAEpB,OAAI,IAAI,OAAO,IAAI,CAAC;;;;;;;;;;AAW1B,SAAgB,qBAAqB,SAAuC;CAC1E,MAAM,WAAW,cAAc,QAAQ;CACvC,MAAM,SAASJ,kBAAK,aAAa,SAAS;AAC1C,QAAO,GAAG,gBAAgB,MAAM,WAAW;AACzC,SAAO,IAAI,mCAAmC;GAC9C;AACF,QAAO"}