UNPKG

inngest

Version:

Official SDK for Inngest.com. Inngest is the reliability layer for modern applications. Inngest combines durable execution, events, and queues into a zero-infra platform with built-in observability.

1 lines 7.61 kB
{"version":3,"file":"node.cjs","names":["frameworkName: SupportedFrameworkName","URL","InngestCommHandler","http"],"sources":["../src/node.ts"],"sourcesContent":["import http from \"node:http\";\nimport { PassThrough } from \"node:stream\";\nimport type { TLSSocket } from \"node:tls\";\nimport { URL } from \"node:url\";\nimport {\n InngestCommHandler,\n type ServeHandlerOptions,\n type SyncHandlerOptions,\n} from \"./components/InngestCommHandler.ts\";\nimport type { 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 request body as text\n */\nasync function readRequestBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let body = \"\";\n req.on(\"data\", (chunk) => {\n body += chunk;\n });\n req.on(\"end\", () => {\n resolve(body);\n });\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 _createResProxy = (\n res: http.ServerResponse,\n): {\n proxy: http.ServerResponse;\n data: Promise<string>;\n} => {\n // We tap the response so that we can capture data being output to convert\n // it to the format we need for checkpointing sync responses with\n // `checkpointResponse()`.\n const resChunks: Uint8Array[] = [];\n\n const tap = new PassThrough();\n tap.on(\"data\", (chunk) => resChunks.push(chunk));\n\n const data = new Promise<string>((resolve, reject) => {\n tap.on(\"end\", () => {\n resolve(Buffer.concat(resChunks).toString());\n });\n\n // TODO reject when?\n\n tap.pipe(res);\n });\n\n const proxy = new Proxy(res, {\n get(target, prop) {\n if (prop === \"write\") return tap.write.bind(tap);\n if (prop === \"end\") return tap.end.bind(tap);\n\n return Reflect.get(target, prop);\n },\n });\n\n return { proxy, data };\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: async () => 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"],"mappings":";;;;;;;;;;;AAeA,MAAaA,gBAAwC;;;;AAKrD,eAAe,gBAAgB,KAA4C;AACzE,QAAO,IAAI,SAAS,YAAY;EAC9B,IAAI,OAAO;AACX,MAAI,GAAG,SAAS,UAAU;AACxB,WAAQ;IACR;AACF,MAAI,GAAG,aAAa;AAClB,WAAQ,KAAK;IACb;GACF;;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;;AAuCvC,MAAM,eAAe,YAAsD;AAoDzE,QAnDgB,IAAIC,8CAAmB;EACrC;EACA,GAAG;EACH,UAAU,KAA2B,QAA6B;AAChE,UAAO;IACL,MAAM,YAAY,gBAAgB,IAAI;IACtC,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"}