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 • 15.6 kB
Source Map (JSON)
{"version":3,"file":"next.cjs","names":["frameworkName: SupportedFrameworkName","InngestEndpointAdapter","absoluteUrl: URL | undefined","host","scheme: \"http\" | \"https\"","getResponse","res","headers: Record<string, string>","InngestCommHandler"],"sources":["../src/next.ts"],"sourcesContent":["/**\n * An adapter for Next.js to serve and register any declared functions with\n * Inngest, making them available to be triggered by events.\n *\n * Supports Next.js 12+, both serverless and edge.\n *\n * @example Next.js <=12 or the pages router can export the handler directly\n * ```ts\n * export default serve({ client: inngest, functions: [fn1, fn2] });\n * ```\n *\n * @example Next.js >=13 with the `app` dir must export individual methods\n * ```ts\n * export const { GET, POST, PUT } = serve({\n * client: inngest,\n * functions: [fn1, fn2],\n * });\n * ```\n *\n * @module\n */\n\nimport type { NextApiRequest, NextApiResponse } from \"next\";\nimport type { NextRequest } from \"next/server\";\nimport type { Inngest } from \"./components/Inngest.ts\";\nimport {\n type ActionResponse,\n InngestCommHandler,\n type ServeHandlerOptions,\n type SyncHandlerOptions,\n} from \"./components/InngestCommHandler.ts\";\nimport { InngestEndpointAdapter } from \"./components/InngestEndpointAdapter.ts\";\nimport { getResponse } from \"./helpers/env.ts\";\nimport type { Either } from \"./helpers/types.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 = \"nextjs\";\n\n/**\n * The shape of a request handler, supporting Next.js 12+.\n *\n * We are intentionally abstract with the arguments here, as Next.js's type\n * checking when building varies wildly between major versions; specifying\n * different types (even optional types) here can cause issues with the build.\n *\n * This change was initially made for Next.js 15, which specifies the second\n * argument as `RouteContext`, whereas Next.js 13 and 14 omit it and Next.js 12\n * provides a `NextApiResponse`, which is varies based on the execution\n * environment used (edge vs serverless).\n */\nexport type RequestHandler = (\n expectedReq: NextRequest,\n res: unknown,\n) => Promise<Response>;\n\nconst isRecord = (val: unknown): val is Record<string, unknown> => {\n return typeof val === \"object\" && val !== null;\n};\n\nconst isFunction = (val: unknown): val is (...args: unknown[]) => unknown => {\n return typeof val === \"function\";\n};\n\nconst isNext12ApiResponse = (val: unknown): val is NextApiResponse => {\n return (\n isRecord(val) &&\n isFunction(val.setHeader) &&\n isFunction(val.status) &&\n isFunction(val.send)\n );\n};\n\n/**\n * In Next.js, serve and register any declared functions with Inngest, making\n * them available to be triggered by events.\n *\n * Supports Next.js 12+, both serverless and edge.\n *\n * @example Next.js <=12 or the pages router can export the handler directly\n * ```ts\n * export default serve({ client: inngest, functions: [fn1, fn2] });\n * ```\n *\n * @example Next.js >=13 with the `app` dir must export individual methods\n * ```ts\n * export const { GET, POST, PUT } = serve({\n * client: inngest,\n * functions: [fn1, fn2],\n * });\n * ```\n *\n * @public\n */\n// Has explicit return type to avoid JSR-defined \"slow types\"\nexport const serve = (\n options: ServeHandlerOptions,\n): RequestHandler & {\n GET: RequestHandler;\n POST: RequestHandler;\n PUT: RequestHandler;\n} => {\n const handler = serveCommHandler(options);\n\n /**\n * Next.js 13 uses\n * {@link https://beta.nextjs.org/docs/routing/route-handlers Route Handlers}\n * to declare API routes instead of a generic catch-all method that was\n * available using the `pages/api` directory.\n *\n * This means that users must now export a function for each method supported\n * by the endpoint. For us, this means requiring a user explicitly exports\n * `GET`, `POST`, and `PUT` functions.\n *\n * Because of this, we'll add circular references to those property names of\n * the returned handler, meaning we can write some succinct code to export\n * them. Thanks, @goodoldneon.\n *\n * @example\n * ```ts\n * export const { GET, POST, PUT } = serve(...);\n * ```\n *\n * See {@link https://beta.nextjs.org/docs/routing/route-handlers}\n */\n const baseFn = handler.createHandler();\n\n const fn = baseFn.bind(null, undefined);\n\n /**\n * Ensure we have a non-variadic length to avoid issues with forced type\n * checking.\n */\n Object.defineProperty(fn, \"length\", { value: 1 });\n\n type Fn = typeof fn;\n\n const handlerFn = Object.defineProperties(fn, {\n GET: { value: baseFn.bind(null, \"GET\") },\n POST: { value: baseFn.bind(null, \"POST\") },\n PUT: { value: baseFn.bind(null, \"PUT\") },\n }) as Fn & {\n GET: Fn;\n POST: Fn;\n PUT: Fn;\n };\n\n return handlerFn;\n};\n\n/**\n * In Next.js, create a function that can wrap any endpoint to be able to use\n * steps seamlessly within that API.\n *\n * Supports Next.js 12+, both serverless and edge.\n *\n * @example Next.js >=13 with the `app` dir\n * ```ts\n * // app/api/my-endpoint/route.ts\n * import { Inngest, step } from \"inngest\";\n * import { endpointAdapter } from \"inngest/next\";\n *\n * const inngest = new Inngest({\n * id: \"my-app\",\n * endpointAdapter,\n * });\n *\n * export const GET = inngest.endpoint(async (req) => {\n * const foo = await step.run(\"my-step\", () => ({ foo: \"bar\" }));\n *\n * return new Response(`Result: ${JSON.stringify(foo)}`);\n * });\n * ```\n */\nexport const endpointAdapter = InngestEndpointAdapter.create((options) => {\n return syncCommHandler(options, options).createSyncHandler();\n});\n\n/**\n * Creates the handler actions object used by InngestCommHandler.\n * Extracted to share logic between serve() and endpointAdapter().\n */\nconst createHandlerActions = (\n req: Either<NextApiRequest, NextRequest>,\n res: unknown,\n options: RegisterOptions & { client: Inngest.Like },\n reqMethod?: \"GET\" | \"POST\" | \"PUT\",\n) => {\n const getHeader = (key: string): string | null | undefined => {\n const header =\n typeof req.headers.get === \"function\"\n ? req.headers.get(key)\n : req.headers[key];\n\n return Array.isArray(header) ? header[0] : header;\n };\n\n return {\n body: async () => {\n if (req.text) {\n return req.text();\n }\n if (req.body instanceof ReadableStream) {\n return readStream(req.body);\n }\n // Unreachable?\n return req.body;\n },\n headers: getHeader,\n method: () => {\n /**\n * `req.method`, though types say otherwise, is not available in Next.js\n * 13 {@link https://beta.nextjs.org/docs/routing/route-handlers Route Handlers}.\n *\n * Therefore, we must try to set the method ourselves where we know it.\n */\n const method = reqMethod || req.method || \"\";\n return method;\n },\n queryString: (key: string, url: URL) => {\n const qs = req.query?.[key] || url.searchParams.get(key);\n return Array.isArray(qs) ? qs[0] : qs;\n },\n\n url: () => {\n let absoluteUrl: URL | undefined;\n try {\n absoluteUrl = new URL(req.url as string);\n } catch {\n // no-op\n }\n\n if (absoluteUrl) {\n /**\n * `req.url` here should may be the full URL, including query string.\n * There are some caveats, however, where Next.js will obfuscate\n * the host. For example, in the case of `host.docker.internal`,\n * Next.js will instead set the host here to `localhost`.\n *\n * To avoid this, we'll try to parse the URL from `req.url`, but\n * also use the `host` header if it's available.\n */\n const host = options.serveOrigin || getHeader(\"host\");\n if (host) {\n const hostWithProtocol = new URL(\n host.includes(\"://\") ? host : `${absoluteUrl.protocol}//${host}`,\n );\n\n absoluteUrl.protocol = hostWithProtocol.protocol;\n absoluteUrl.host = hostWithProtocol.host;\n absoluteUrl.port = hostWithProtocol.port;\n absoluteUrl.username = hostWithProtocol.username;\n absoluteUrl.password = hostWithProtocol.password;\n }\n\n return absoluteUrl;\n }\n\n let scheme: \"http\" | \"https\" = \"https\";\n const host = options.serveOrigin || getHeader(\"host\") || \"\";\n\n try {\n if (process.env.NODE_ENV === \"development\") {\n scheme = \"http\";\n }\n } catch (_err) {\n // no-op\n }\n\n const url = new URL(req.url as string, `${scheme}://${host}`);\n\n return url;\n },\n transformResponse: ({\n body,\n headers,\n status,\n }: ActionResponse<string>): Response => {\n /**\n * Carefully attempt to set headers and data on the response object\n * for Next.js 12 support.\n *\n * This also assumes that we're not using Next.js 15, where the `res`\n * object is repopulated as a `RouteContext` object. We expect these\n * methods to NOT be defined in Next.js 15.\n *\n * We could likely use `instanceof ServerResponse` to better check the\n * type of this, though Next.js 12 had issues with this due to not\n * instantiating the response correctly.\n */\n if (isNext12ApiResponse(res)) {\n for (const [key, value] of Object.entries(headers)) {\n res.setHeader(key, value);\n }\n\n res.status(status);\n res.send(body);\n\n /**\n * If we're here, we're in a serverless endpoint (not edge), so\n * we've correctly sent the response and can return `undefined`.\n *\n * Next.js 13 edge requires that the return value is typed as\n * `Response`, so we still enforce that as we cannot dynamically\n * adjust typing based on the environment.\n */\n return undefined as unknown as Response;\n }\n\n /**\n * If we're here, we're in an edge environment and need to return a\n * `Response` object.\n *\n * We also don't know if the current environment has a native\n * `Response` object, so we'll grab that first.\n */\n const Res = getResponse();\n return new Res(body, { status, headers });\n },\n transformStreamingResponse: ({\n body,\n headers,\n status,\n }: ActionResponse<ReadableStream>): Response => {\n return new Response(body, { status, headers });\n },\n experimentalTransformSyncResponse: async (data: unknown) => {\n const res = data as Response;\n\n const headers: Record<string, string> = {};\n res.headers.forEach((v, k) => {\n headers[k] = v;\n });\n\n return {\n headers: headers,\n status: res.status,\n body: await res.clone().text(),\n };\n },\n };\n};\n\n/**\n * Creates an InngestCommHandler for serve() - includes reqMethod parameter\n * for binding to specific HTTP methods.\n */\nconst serveCommHandler = (\n options: RegisterOptions & { client: Inngest.Like },\n) => {\n return new InngestCommHandler({\n frameworkName,\n ...options,\n handler: (\n reqMethod: \"GET\" | \"POST\" | \"PUT\" | undefined,\n ...args: Parameters<RequestHandler>\n ) => {\n const [expectedReq, res] = args;\n const req = expectedReq as Either<NextApiRequest, NextRequest>;\n return createHandlerActions(req, res, options, reqMethod);\n },\n });\n};\n\n/**\n * Creates an InngestCommHandler for endpointAdapter() - no reqMethod parameter,\n * uses the standard RequestHandler signature.\n */\nconst syncCommHandler = (\n options: RegisterOptions & { client: Inngest.Like },\n syncOptions: SyncHandlerOptions,\n) => {\n return new InngestCommHandler({\n frameworkName,\n ...options,\n syncOptions,\n handler: (...args: Parameters<RequestHandler>) => {\n const [expectedReq, res] = args;\n const req = expectedReq as Either<NextApiRequest, NextRequest>;\n return createHandlerActions(req, res, options);\n },\n });\n};\n\nasync function readStream(stream: ReadableStream): Promise<string> {\n const chunks = [];\n const reader = stream.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n chunks.push(value);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n"],"mappings":"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"}