inngest 4.2.5 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/api/api.cjs +1 -1
  3. package/api/api.js +1 -1
  4. package/components/Inngest.cjs +1 -1
  5. package/components/Inngest.d.cts +7 -1
  6. package/components/Inngest.d.cts.map +1 -1
  7. package/components/Inngest.d.ts +7 -1
  8. package/components/Inngest.d.ts.map +1 -1
  9. package/components/Inngest.js +1 -1
  10. package/components/InngestCommHandler.cjs +60 -28
  11. package/components/InngestCommHandler.cjs.map +1 -1
  12. package/components/InngestCommHandler.d.cts.map +1 -1
  13. package/components/InngestCommHandler.d.ts.map +1 -1
  14. package/components/InngestCommHandler.js +60 -28
  15. package/components/InngestCommHandler.js.map +1 -1
  16. package/components/InngestStepTools.cjs +3 -7
  17. package/components/InngestStepTools.cjs.map +1 -1
  18. package/components/InngestStepTools.d.cts +10 -7
  19. package/components/InngestStepTools.d.cts.map +1 -1
  20. package/components/InngestStepTools.d.ts +10 -7
  21. package/components/InngestStepTools.d.ts.map +1 -1
  22. package/components/InngestStepTools.js +3 -7
  23. package/components/InngestStepTools.js.map +1 -1
  24. package/components/connect/strategies/core/connection.cjs +91 -11
  25. package/components/connect/strategies/core/connection.cjs.map +1 -1
  26. package/components/connect/strategies/core/connection.js +91 -11
  27. package/components/connect/strategies/core/connection.js.map +1 -1
  28. package/components/connect/strategies/core/heartbeat.cjs +2 -1
  29. package/components/connect/strategies/core/heartbeat.cjs.map +1 -1
  30. package/components/connect/strategies/core/heartbeat.js +2 -1
  31. package/components/connect/strategies/core/heartbeat.js.map +1 -1
  32. package/components/connect/strategies/core/requestProcessor.cjs +27 -4
  33. package/components/connect/strategies/core/requestProcessor.cjs.map +1 -1
  34. package/components/connect/strategies/core/requestProcessor.js +27 -4
  35. package/components/connect/strategies/core/requestProcessor.js.map +1 -1
  36. package/components/connect/strategies/core/types.cjs +21 -0
  37. package/components/connect/strategies/core/types.cjs.map +1 -0
  38. package/components/connect/strategies/core/types.js +20 -0
  39. package/components/connect/strategies/core/types.js.map +1 -0
  40. package/components/connect/types.cjs.map +1 -1
  41. package/components/connect/types.d.cts +18 -0
  42. package/components/connect/types.d.cts.map +1 -1
  43. package/components/connect/types.d.ts +18 -0
  44. package/components/connect/types.d.ts.map +1 -1
  45. package/components/connect/types.js.map +1 -1
  46. package/components/execution/engine.cjs +1 -1
  47. package/components/execution/engine.js +1 -1
  48. package/components/execution/otel/middleware.d.cts +12 -6
  49. package/components/execution/otel/middleware.d.cts.map +1 -1
  50. package/components/execution/otel/middleware.d.ts +12 -6
  51. package/components/execution/otel/middleware.d.ts.map +1 -1
  52. package/components/middleware/manager.cjs +1 -1
  53. package/components/middleware/manager.cjs.map +1 -1
  54. package/components/middleware/manager.js +2 -2
  55. package/components/middleware/manager.js.map +1 -1
  56. package/components/middleware/utils.cjs +4 -3
  57. package/components/middleware/utils.cjs.map +1 -1
  58. package/components/middleware/utils.js +4 -3
  59. package/components/middleware/utils.js.map +1 -1
  60. package/components/realtime/types.d.cts +4 -4
  61. package/components/realtime/types.d.cts.map +1 -1
  62. package/components/realtime/types.d.ts +4 -4
  63. package/components/realtime/types.d.ts.map +1 -1
  64. package/helpers/consts.cjs +1 -0
  65. package/helpers/consts.cjs.map +1 -1
  66. package/helpers/consts.d.cts +1 -0
  67. package/helpers/consts.d.cts.map +1 -1
  68. package/helpers/consts.d.ts +1 -0
  69. package/helpers/consts.d.ts.map +1 -1
  70. package/helpers/consts.js +1 -0
  71. package/helpers/consts.js.map +1 -1
  72. package/helpers/env.cjs +2 -1
  73. package/helpers/env.cjs.map +1 -1
  74. package/helpers/env.js +2 -1
  75. package/helpers/env.js.map +1 -1
  76. package/helpers/net.cjs +3 -2
  77. package/helpers/net.cjs.map +1 -1
  78. package/helpers/net.js +3 -2
  79. package/helpers/net.js.map +1 -1
  80. package/helpers/strings.cjs +15 -5
  81. package/helpers/strings.cjs.map +1 -1
  82. package/helpers/strings.d.cts.map +1 -1
  83. package/helpers/strings.d.ts.map +1 -1
  84. package/helpers/strings.js +15 -6
  85. package/helpers/strings.js.map +1 -1
  86. package/helpers/temporal.cjs +2 -0
  87. package/helpers/temporal.d.ts +3 -0
  88. package/helpers/temporal.d.ts.map +1 -1
  89. package/helpers/temporal.js +1 -1
  90. package/package.json +1 -1
  91. package/react.d.cts.map +1 -1
  92. package/types.cjs.map +1 -1
  93. package/types.d.cts +5 -4
  94. package/types.d.cts.map +1 -1
  95. package/types.d.ts +5 -4
  96. package/types.d.ts.map +1 -1
  97. package/types.js.map +1 -1
  98. package/version.cjs +1 -1
  99. package/version.cjs.map +1 -1
  100. package/version.d.cts +1 -1
  101. package/version.d.ts +1 -1
  102. package/version.js +1 -1
  103. package/version.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"InngestCommHandler.js","names":["acc","defaultStreamingOption: typeof this.streaming","v","body","result","redirectUrl: string","method","headers: Record<string, string>","signature: string | undefined","signature","actionResponseVersion: ExecutionVersion | null | undefined","chainResult: Promise<Middleware.Response>","requestInfo: Middleware.Request","shouldStream: boolean","actions: HandlerResponseWithErrors","args","fn: { fn: InngestFunction.Any; onFailure: boolean } | undefined","fnId: string | undefined","probe","probeEnum","headerReqVersion: ExecutionVersion | undefined","runCompleteOp: OutgoingOp","deployId","version","data","executionOptions: CreateExecutionOptions","body: InBandRegisterRequest","introspection:\n | UnauthenticatedIntrospection\n | AuthenticatedIntrospection","res: globalThis.Response","err: unknown","data: z.input<typeof registerResSchema>","status: number","error: string","skipped: boolean","modified: boolean","#verifySignature"],"sources":["../../src/components/InngestCommHandler.ts"],"sourcesContent":["import { z } from \"zod/v3\";\nimport {\n defaultMaxRetries,\n ExecutionVersion,\n envKeys,\n forwardedHeaders,\n headerKeys,\n internalEvents,\n logPrefix,\n probe as probeEnum,\n queryKeys,\n syncKind,\n} from \"../helpers/consts.ts\";\nimport { enumFromValue } from \"../helpers/enum.ts\";\nimport {\n checkModeConfiguration,\n type Env,\n getPlatformName,\n getProcessEnv,\n inngestHeaders,\n parseAsBoolean,\n protectEnv,\n} from \"../helpers/env.ts\";\nimport { rethrowError, serializeError } from \"../helpers/errors.ts\";\nimport {\n createVersionSchema,\n type FnData,\n fetchAllFnData,\n parseFnData,\n undefinedToNull,\n} from \"../helpers/functions.ts\";\nimport { warnOnce } from \"../helpers/log.ts\";\nimport { fetchWithAuthFallback, signDataWithKey } from \"../helpers/net.ts\";\nimport { runAsPromise } from \"../helpers/promises.ts\";\nimport { ServerTiming } from \"../helpers/ServerTiming.ts\";\nimport { createStream } from \"../helpers/stream.ts\";\nimport {\n hashEventKey,\n hashSigningKey,\n stringify,\n timingSafeEqual,\n} from \"../helpers/strings.ts\";\nimport { isRecord, type MaybePromise } from \"../helpers/types.ts\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport {\n type APIStepPayload,\n AsyncResponseType,\n type AsyncResponseValue,\n type AuthenticatedIntrospection,\n DefaultMaxRuntime,\n type EventPayload,\n type FunctionConfig,\n functionConfigSchema,\n type InBandRegisterRequest,\n inBandSyncRequestBodySchema,\n type OutgoingOp,\n type RegisterOptions,\n type RegisterRequest,\n StepMode,\n StepOpCode,\n type UnauthenticatedIntrospection,\n} from \"../types.ts\";\nimport { version } from \"../version.ts\";\nimport { getAsyncCtx } from \"./execution/als.ts\";\nimport { _internals } from \"./execution/engine.ts\";\nimport {\n type ExecutionResult,\n type ExecutionResultHandler,\n type ExecutionResultHandlers,\n type InngestExecutionOptions,\n PREFERRED_ASYNC_EXECUTION_VERSION,\n} from \"./execution/InngestExecution.ts\";\nimport { type Inngest, internalLoggerSymbol } from \"./Inngest.ts\";\nimport {\n type CreateExecutionOptions,\n InngestFunction,\n} from \"./InngestFunction.ts\";\nimport { buildWrapRequestChain, type Middleware } from \"./middleware/index.ts\";\n\n// A response object for when an internal server error occurs. When that\n// happens, we don't to leak any internal details to the client.\nconst internalServerErrorResponse = {\n body: stringify({ code: \"internal_server_error\" }),\n headers: { \"Content-Type\": \"application/json\" },\n status: 500,\n version: undefined,\n} as const;\n\n/**\n * A set of options that can be passed to a serve handler, intended to be used\n * by internal and custom serve handlers to provide a consistent interface.\n *\n * @public\n */\nexport interface ServeHandlerOptions extends RegisterOptions {\n /**\n * The `Inngest` instance used to declare all functions.\n */\n client: Inngest.Like;\n\n /**\n * An array of the functions to serve and register with Inngest.\n */\n functions: readonly InngestFunction.Like[];\n}\n\n/**\n * Parameters passed to the asyncRedirectUrl function.\n */\nexport interface AsyncRedirectUrlParams {\n /**\n * The unique identifier for this run.\n */\n runId: string;\n\n /**\n * The token used to authenticate the request to fetch run output.\n */\n token: string;\n}\n\nexport interface SyncHandlerOptions extends RegisterOptions {\n /**\n * The `Inngest` instance used to declare all functions.\n */\n client: Inngest.Like;\n\n /**\n * The type of response you wish to return to an API endpoint when using steps\n * within it and we must transition to {@link StepMode.Async}.\n *\n * In most cases, this defaults to {@link AsyncResponseType.Redirect}.\n */\n asyncResponse?: AsyncResponseValue;\n\n /**\n * Custom URL to redirect to when switching from sync to async mode.\n *\n * Can be:\n * - A string path (e.g., \"/api/inngest/poll\") - resolved relative to request origin\n * - A function that receives `{ runId, token }` and returns a full URL\n *\n * When a string path is provided, `runId` and `token` query parameters are\n * automatically appended.\n *\n * @example\n * ```ts\n * // String path - resolved relative to request origin\n * asyncRedirectUrl: \"/api/inngest/poll\"\n *\n * // Function - full control over URL construction\n * asyncRedirectUrl: ({ runId, token }) =>\n * `https://my-app.com/poll?run=${runId}&t=${token}`\n * ```\n */\n asyncRedirectUrl?:\n | string\n | ((params: AsyncRedirectUrlParams) => string | Promise<string>);\n\n /**\n * If defined, this sets the function ID that represents this endpoint.\n * Without this set, it defaults to using the detected method and path of the\n * request, for example: `GET /api/my-endpoint`.\n */\n functionId?: string;\n\n /**\n * Specifies the maximum number of retries for all steps.\n *\n * Can be a number from `0` to `20`. Defaults to `3`.\n */\n retries?:\n | 0\n | 1\n | 2\n | 3\n | 4\n | 5\n | 6\n | 7\n | 8\n | 9\n | 10\n | 11\n | 12\n | 13\n | 14\n | 15\n | 16\n | 17\n | 18\n | 19\n | 20;\n}\n\nexport type SyncAdapterOptions = Omit<SyncHandlerOptions, \"client\">;\n\nexport interface InternalServeHandlerOptions extends ServeHandlerOptions {\n /**\n * Can be used to override the framework name given to a particular serve\n * handler.\n */\n frameworkName?: string;\n\n /**\n * Can be used to force the handler to always execute functions regardless of\n * the request method or other factors.\n *\n * This is primarily intended for use with Inngest in APIs, where requests may\n * not have the usual shape of an Inngest payload, but we want to pull data\n * and execute.\n */\n // forceExecution?: boolean;\n}\n\ninterface InngestCommHandlerOptions<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Input extends any[] = any[],\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Output = any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n StreamOutput = any,\n> extends RegisterOptions {\n /**\n * The name of the framework this handler is designed for. Should be\n * lowercase, alphanumeric characters inclusive of `-` and `/`.\n *\n * This should never be defined by the user; a {@link ServeHandler} should\n * abstract this.\n */\n frameworkName: string;\n\n /**\n * The name of this serve handler, e.g. `\"My App\"`. It's recommended that this\n * value represents the overarching app/service that this set of functions is\n * being served from.\n *\n * This can also be an `Inngest` client, in which case the name given when\n * instantiating the client is used. This is useful if you're sending and\n * receiving events from the same service, as you can reuse a single\n * definition of Inngest.\n */\n client: Inngest.Like;\n\n /**\n * An array of the functions to serve and register with Inngest.\n */\n functions?: readonly InngestFunction.Like[];\n\n /**\n * The `handler` is the function that will be called with your framework's\n * request arguments and returns a set of functions that the SDK will use to\n * access various parts of the request, such as the body, headers, and query\n * string parameters.\n *\n * It also defines how to transform a response from the SDK into a response\n * that your framework can understand, ensuring headers, status codes, and\n * body are all set correctly.\n *\n * @example\n * ```ts\n * function handler (req: Request, res: Response) {\n * return {\n * method: () => req.method,\n * body: () => req.json(),\n * headers: (key) => req.headers.get(key),\n * url: () => req.url,\n * transformResponse: ({ body, headers, status }) => {\n * return new Response(body, { status, headers });\n * },\n * };\n * };\n * ```\n *\n * See any existing handler for a full example.\n */\n handler: Handler<Input, Output, StreamOutput>;\n\n skipSignatureValidation?: boolean;\n\n /**\n * The default `maxRuntime` in milliseconds to use for checkpointing when the\n * user hasn't explicitly configured one at the function or client level.\n *\n * Defaults to {@link DefaultMaxRuntime.serve} (10 seconds).\n */\n defaultMaxRuntime?: DefaultMaxRuntime;\n\n /**\n * Options for when this comm handler executes a synchronous (API) function.\n */\n syncOptions?: SyncHandlerOptions;\n}\n\n/**\n * A schema for the response from Inngest when registering.\n */\nconst registerResSchema = z.object({\n status: z.number().default(200),\n skipped: z.boolean().optional().default(false),\n modified: z.boolean().optional().default(false),\n error: z.string().default(\"Successfully registered\"),\n});\n\n/**\n * `InngestCommHandler` is a class for handling incoming requests from Inngest (or\n * Inngest's tooling such as the dev server or CLI) and taking appropriate\n * action for any served functions.\n *\n * All handlers (Next.js, RedwoodJS, Remix, Deno Fresh, etc.) are created using\n * this class; the exposed `serve` function will - most commonly - create an\n * instance of `InngestCommHandler` and then return `instance.createHandler()`.\n *\n * See individual parameter details for more information, or see the\n * source code for an existing handler, e.g.\n * {@link https://github.com/inngest/inngest-js/blob/main/src/next.ts}\n *\n * @example\n * ```\n * // my-custom-handler.ts\n * import {\n * InngestCommHandler,\n * type ServeHandlerOptions,\n * } from \"./components/InngestCommHandler\";\n *\n * export const serve = (options: ServeHandlerOptions) => {\n * const handler = new InngestCommHandler({\n * frameworkName: \"my-custom-handler\",\n * ...options,\n * handler: (req: Request) => {\n * return {\n * body: () => req.json(),\n * headers: (key) => req.headers.get(key),\n * method: () => req.method,\n * url: () => new URL(req.url, `https://${req.headers.get(\"host\") || \"\"}`),\n * transformResponse: ({ body, status, headers }) => {\n * return new Response(body, { status, headers });\n * },\n * };\n * },\n * });\n *\n * return handler.createHandler();\n * };\n * ```\n *\n * @public\n */\nexport class InngestCommHandler<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Input extends any[] = any[],\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Output = any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n StreamOutput = any,\n> {\n /**\n * The handler specified during instantiation of the class.\n */\n public readonly handler: Handler;\n\n /**\n * The URL of the Inngest function registration endpoint.\n */\n private readonly inngestRegisterUrl: URL;\n\n /**\n * The name of the framework this handler is designed for. Should be\n * lowercase, alphanumeric characters inclusive of `-` and `/`.\n */\n protected readonly frameworkName: string;\n\n /**\n * The origin used to access the Inngest serve endpoint, e.g.:\n *\n * \"https://myapp.com\" or \"https://myapp.com:1234\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom origin here to ensure that the path is reported\n * correctly when registering functions with Inngest.\n *\n * To also provide a custom path, use `servePath`.\n */\n private readonly _serveOrigin: string | undefined;\n\n /**\n * The path to the Inngest serve endpoint. e.g.:\n *\n * \"/some/long/path/to/inngest/endpoint\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom path (excluding the hostname) here to ensure that the\n * path is reported correctly when registering functions with Inngest.\n *\n * To also provide a custom hostname, use `serveOrigin`.\n */\n private readonly _servePath: string | undefined;\n\n protected readonly streaming: RegisterOptions[\"streaming\"];\n\n /**\n * A private collection of just Inngest functions, as they have been passed\n * when instantiating the class.\n */\n private readonly rawFns: InngestFunction.Any[];\n\n private readonly client: Inngest.Any;\n\n /**\n * A private collection of functions that are being served. This map is used\n * to find and register functions when interacting with Inngest Cloud.\n */\n private readonly fns: Record<\n string,\n { fn: InngestFunction.Any; onFailure: boolean }\n > = {};\n\n private env: Env = getProcessEnv();\n\n private allowExpiredSignatures: boolean;\n\n private readonly _options: InngestCommHandlerOptions<\n Input,\n Output,\n StreamOutput\n >;\n\n private readonly skipSignatureValidation: boolean;\n\n private readonly defaultMaxRuntime: DefaultMaxRuntime;\n\n constructor(options: InngestCommHandlerOptions<Input, Output, StreamOutput>) {\n // Set input options directly so we can reference them later\n this._options = options;\n\n /**\n * v2 -> v3 migration error.\n * TODO: do we need to handle people going from v2->v4?\n *\n * If a serve handler is passed a client as the first argument, it'll be\n * spread in to these options. We should be able to detect this by picking\n * up a unique property on the object.\n */\n if (Object.hasOwn(options, \"eventKey\")) {\n throw new Error(\n `${logPrefix} You've passed an Inngest client as the first argument to your serve handler. This is no longer supported in v3; please pass the Inngest client as the \\`client\\` property of an options object instead. See https://www.inngest.com/docs/sdk/migration`,\n );\n }\n\n this.frameworkName = options.frameworkName;\n this.client = options.client as Inngest.Any;\n this.defaultMaxRuntime =\n options.defaultMaxRuntime ?? DefaultMaxRuntime.serve;\n\n this.handler = options.handler as Handler;\n\n /**\n * Provide a hidden option to allow expired signatures to be accepted during\n * testing.\n */\n this.allowExpiredSignatures = Boolean(\n // biome-ignore lint/complexity/noArguments: intentional\n arguments[\"0\"]?.__testingAllowExpiredSignatures,\n );\n\n // Ensure we filter any undefined functions in case of missing imports.\n this.rawFns = (options.functions?.filter(Boolean) ??\n []) as InngestFunction.Any[];\n\n if (this.rawFns.length !== (options.functions ?? []).length) {\n this.client[internalLoggerSymbol].warn(\n `Some functions passed to serve() are undefined and misconfigured. Please check your imports.`,\n );\n }\n\n this.fns = this.rawFns.reduce<\n Record<string, { fn: InngestFunction.Any; onFailure: boolean }>\n >((acc, fn) => {\n const configs = fn[\"getConfig\"]({\n baseUrl: new URL(\"https://example.com\"),\n appPrefix: this.client.id,\n });\n\n const fns = configs.reduce((acc, { id }, index) => {\n return { ...acc, [id]: { fn, onFailure: Boolean(index) } };\n }, {});\n\n // biome-ignore lint/complexity/noForEach: intentional\n configs.forEach(({ id }) => {\n if (acc[id]) {\n throw new Error(\n `Duplicate function ID \"${id}\"; please change a function's name or provide an explicit ID to avoid conflicts.`,\n );\n }\n });\n\n return {\n ...acc,\n ...fns,\n };\n }, {});\n\n this.inngestRegisterUrl = new URL(\"/fn/register\", this.client.apiBaseUrl);\n\n this._serveOrigin =\n options.serveOrigin || this.env[envKeys.InngestServeOrigin];\n this._servePath = options.servePath || this.env[envKeys.InngestServePath];\n\n this.skipSignatureValidation = options.skipSignatureValidation || false;\n\n const defaultStreamingOption: typeof this.streaming = false;\n this.streaming = z\n .boolean()\n .default(defaultStreamingOption)\n .catch((ctx) => {\n this.client[internalLoggerSymbol].warn(\n { input: ctx.input, default: defaultStreamingOption },\n \"Unknown streaming option; using default\",\n );\n\n return defaultStreamingOption;\n })\n .parse(\n options.streaming || parseAsBoolean(this.env[envKeys.InngestStreaming]),\n );\n\n // Early validation for environments where process.env is available (Node.js).\n // Edge environments will skip this and validate at request time instead.\n this.client.setEnvVars(this.env);\n }\n\n /**\n * The origin used to access the Inngest serve endpoint, e.g.:\n *\n * \"https://myapp.com\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom origin here to ensure that the path is reported\n * correctly when registering functions with Inngest.\n *\n * To also provide a custom path, use `servePath`.\n */\n protected get serveOrigin(): string | undefined {\n if (this._serveOrigin) {\n return this._serveOrigin;\n }\n\n const envOrigin = this.env[envKeys.InngestServeOrigin];\n if (envOrigin) {\n return envOrigin;\n }\n\n const envHost = this.env[envKeys.InngestServeHost];\n if (envHost) {\n warnOnce(\n this.client[internalLoggerSymbol],\n \"serve-host-deprecated\",\n \"INNGEST_SERVE_HOST is deprecated; use INNGEST_SERVE_ORIGIN instead\",\n );\n return envHost;\n }\n\n return undefined;\n }\n\n /**\n * The path to the Inngest serve endpoint. e.g.:\n *\n * \"/some/long/path/to/inngest/endpoint\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom path (excluding the hostname) here to ensure that the\n * path is reported correctly when registering functions with Inngest.\n *\n * To also provide a custom hostname, use `serveOrigin`.\n *\n * This is a getter to encourage checking the environment for the serve path\n * each time it's accessed, as it may change during execution.\n */\n protected get servePath(): string | undefined {\n return this._servePath || this.env[envKeys.InngestServePath];\n }\n\n private get hashedEventKey(): string | undefined {\n if (!this.client.eventKey) {\n return undefined;\n }\n return hashEventKey(this.client.eventKey);\n }\n\n // hashedSigningKey creates a sha256 checksum of the signing key with the\n // same signing key prefix.\n private get hashedSigningKey(): string | undefined {\n if (!this.client.signingKey) {\n return undefined;\n }\n return hashSigningKey(this.client.signingKey);\n }\n\n private get hashedSigningKeyFallback(): string | undefined {\n if (!this.client.signingKeyFallback) {\n return undefined;\n }\n return hashSigningKey(this.client.signingKeyFallback);\n }\n\n /**\n * Returns a `boolean` representing whether this handler will stream responses\n * or not. Takes into account the user's preference and the platform's\n * capabilities.\n */\n private async shouldStream(\n actions: HandlerResponseWithErrors,\n ): Promise<boolean> {\n const rawProbe = await actions.queryStringWithDefaults(\n \"testing for probe\",\n queryKeys.Probe,\n );\n if (rawProbe !== undefined) {\n return false;\n }\n\n const envStreaming = this.env[envKeys.InngestStreaming];\n if (envStreaming === \"allow\" || envStreaming === \"force\") {\n warnOnce(\n this.client[internalLoggerSymbol],\n \"streaming-allow-force-deprecated\",\n { value: envStreaming },\n `INNGEST_STREAMING=\"${envStreaming}\" is deprecated; set INNGEST_STREAMING=true instead`,\n );\n }\n\n const streamingRequested =\n this.streaming === true ||\n parseAsBoolean(this.env[envKeys.InngestStreaming]) === true ||\n envStreaming === \"allow\" ||\n envStreaming === \"force\";\n\n // We must be able to stream responses to continue.\n if (!actions.transformStreamingResponse) {\n if (streamingRequested) {\n throw new Error(\n `${logPrefix} Streaming has been forced but the serve handler does not support streaming. Please either remove the streaming option or use a serve handler that supports streaming.`,\n );\n }\n return false;\n }\n\n return streamingRequested;\n }\n\n private async isInngestReq(\n actions: HandlerResponseWithErrors,\n ): Promise<boolean> {\n const reqMessage = `checking if this is an Inngest request`;\n\n const [runId, signature] = await Promise.all([\n actions.headers(reqMessage, headerKeys.InngestRunId),\n actions.headers(reqMessage, headerKeys.Signature),\n ]);\n\n // Note that the signature just has to be present; in Dev it'll be empty,\n // but still set to `\"\"`.\n return Boolean(runId && typeof signature === \"string\");\n }\n\n /**\n * Start handling a request, setting up environments, modes, and returning\n * some helpers.\n */\n private async initRequest(...args: Input): Promise<{\n timer: ServerTiming;\n actions: HandlerResponseWithErrors;\n getHeaders: () => Promise<Record<string, string>>;\n }> {\n const timer = new ServerTiming(this.client[internalLoggerSymbol]);\n const actions = await this.getActions(timer, ...args);\n\n const [env, expectedServerKind] = await Promise.all([\n actions.env?.(\"starting to handle request\"),\n actions.headers(\n \"checking expected server kind\",\n headerKeys.InngestServerKind,\n ),\n ]);\n\n // Always make sure to merge whatever env we've been given with\n // `process.env`; some platforms may not provide all the necessary\n // environment variables or may use two sources.\n // Update both handler's env and client's env to ensure consistency.\n this.env = protectEnv({ ...getProcessEnv(), ...env });\n this.client.setEnvVars(this.env);\n\n const headerPromises = forwardedHeaders.map(async (header) => {\n const value = await actions.headers(\n `fetching ${header} for forwarding`,\n header,\n );\n\n return { header, value };\n });\n\n const headersToForwardP = Promise.all(headerPromises).then(\n (fetchedHeaders) => {\n return fetchedHeaders.reduce<Record<string, string>>(\n (acc, { header, value }) => {\n if (value) {\n acc[header] = value;\n }\n\n return acc;\n },\n {},\n );\n },\n );\n\n const getHeaders = async (): Promise<Record<string, string>> => ({\n ...inngestHeaders({\n env: this.env,\n framework: this.frameworkName,\n client: this.client,\n expectedServerKind: expectedServerKind || undefined,\n extras: {\n \"Server-Timing\": timer.getHeader(),\n },\n }),\n ...(await headersToForwardP),\n });\n\n return {\n timer,\n actions,\n getHeaders,\n };\n }\n\n /**\n * `createSyncHandler` should be used to return a type-equivalent version of\n * the `handler` specified during instantiation.\n */\n public createSyncHandler<\n THandler extends (...args: Input) => Promise<Awaited<Output>>,\n >(): (handler: THandler) => THandler {\n // Return a function that can be used to wrap endpoints\n return (handler) => {\n return this.wrapHandler((async (...args) => {\n const reqInit = await this.initRequest(...args);\n\n const fn = new InngestFunction(\n this.client,\n {\n id: this._options.syncOptions?.functionId ?? \"\",\n retries: this._options.syncOptions?.retries ?? defaultMaxRetries,\n },\n () => handler(...args),\n );\n\n // Decide if this request looks like an Inngest request. If it does,\n // we'll just use the regular `serve()` handler for this request, as\n // it's async.\n if (await this.isInngestReq(reqInit.actions)) {\n // If we have a run ID, we can just use the normal serve path\n // return this.createHandler()(...args);\n return this.handleAsyncRequest({\n ...reqInit,\n forceExecution: true,\n args,\n fns: [fn],\n });\n }\n\n // Otherwise, we know this is a sync request, so we can proceed with\n // creating a sync request to Inngest.\n return this.handleSyncRequest({\n ...reqInit,\n args,\n asyncMode:\n this._options.syncOptions?.asyncResponse ??\n AsyncResponseType.Redirect,\n asyncRedirectUrl: this._options.syncOptions?.asyncRedirectUrl,\n fn,\n });\n }) as THandler);\n };\n }\n\n /**\n * `createHandler` should be used to return a type-equivalent version of the\n * `handler` specified during instantiation.\n *\n * @example\n * ```\n * // my-custom-handler.ts\n * import {\n * InngestCommHandler,\n * type ServeHandlerOptions,\n * } from \"./components/InngestCommHandler\";\n *\n * export const serve = (options: ServeHandlerOptions) => {\n * const handler = new InngestCommHandler({\n * frameworkName: \"my-custom-handler\",\n * ...options,\n * handler: (req: Request) => {\n * return {\n * body: () => req.json(),\n * headers: (key) => req.headers.get(key),\n * method: () => req.method,\n * url: () => new URL(req.url, `https://${req.headers.get(\"host\") || \"\"}`),\n * transformResponse: ({ body, status, headers }) => {\n * return new Response(body, { status, headers });\n * },\n * };\n * },\n * });\n *\n * return handler.createHandler();\n * };\n * ```\n */\n public createHandler<\n THandler extends (...args: Input) => Promise<Awaited<Output>>,\n >(): THandler {\n return this.wrapHandler((async (...args) => {\n return this.handleAsyncRequest({\n ...(await this.initRequest(...args)),\n args,\n });\n }) as THandler);\n }\n\n /**\n * Given a set of actions that let us access the incoming request, create an\n * event that repesents a run starting from an HTTP request.\n */\n private async createHttpEvent(\n actions: HandlerResponseWithErrors,\n fn: InngestFunction.Any,\n ): Promise<APIStepPayload> {\n const reason = \"creating sync event\";\n\n const contentTypePromise = actions\n .headers(reason, headerKeys.ContentType)\n .then((v) => v ?? \"\");\n\n const ipPromise = actions\n .headers(reason, headerKeys.ForwardedFor)\n .then((v) => {\n if (v) return v;\n\n return actions.headers(reason, headerKeys.RealIp).then((v) => v ?? \"\");\n });\n\n const methodPromise = actions.method(reason);\n\n const urlPromise = actions.url(reason).then((v) => this.reqUrl(v));\n\n const domainPromise = urlPromise.then(\n (url) => `${url.protocol}//${url.host}`,\n );\n\n const pathPromise = urlPromise.then((url) => url.pathname);\n\n const queryParamsPromise = urlPromise.then((url) =>\n url.searchParams.toString(),\n );\n\n const bodyPromise = actions.body(reason).then((body) => {\n return typeof body === \"string\" ? body : stringify(body);\n });\n\n const [contentType, domain, ip, method, path, queryParams, body] =\n await Promise.all([\n contentTypePromise,\n domainPromise,\n ipPromise,\n methodPromise,\n pathPromise,\n queryParamsPromise,\n bodyPromise,\n ]);\n\n return {\n name: internalEvents.HttpRequest,\n data: {\n content_type: contentType,\n domain,\n ip,\n method,\n path,\n query_params: queryParams,\n body,\n fn: fn.id(),\n },\n };\n }\n\n private async handleSyncRequest({\n timer,\n actions,\n fn,\n asyncMode,\n asyncRedirectUrl,\n args,\n }: {\n timer: ServerTiming;\n actions: HandlerResponseWithErrors;\n fn: InngestFunction.Any;\n asyncMode: AsyncResponseValue;\n asyncRedirectUrl: SyncHandlerOptions[\"asyncRedirectUrl\"];\n args: unknown[];\n }): Promise<Awaited<Output>> {\n // Do we have actions for handling sync requests? We must!\n if (!actions.experimentalTransformSyncResponse) {\n throw new Error(\n \"This platform does not support synchronous Inngest function executions.\",\n );\n }\n\n // Check we're not in a context already...\n const ctx = await getAsyncCtx();\n if (ctx) {\n throw new Error(\n \"We already seem to be in the context of an Inngest execution, but didn't expect to be. Did you already wrap this handler?\",\n );\n }\n\n // We create a new run ID here in the SDK.\n const { ulid } = await import(\"ulid\"); // lazy loading for edge envs\n const runId = ulid();\n const event = await this.createHttpEvent(actions, fn);\n\n const acceptHeader = await actions.headers(\n \"checking accept header\",\n \"Accept\",\n );\n const acceptsSse = acceptHeader?.includes(\"text/event-stream\") ?? false;\n\n const exeVersion = ExecutionVersion.V2;\n\n const exe = fn[\"createExecution\"]({\n partialOptions: {\n client: this.client,\n data: {\n runId,\n event,\n attempt: 0,\n events: [event],\n maxAttempts: fn.opts.retries ?? defaultMaxRetries,\n },\n runId,\n headers: {},\n reqArgs: args,\n stepCompletionOrder: [],\n stepState: {},\n disableImmediateExecution: false,\n isFailureHandler: false,\n acceptsSse,\n timer,\n createResponse: (data: unknown) =>\n actions.experimentalTransformSyncResponse!(\n \"creating sync execution\",\n data,\n ).then((res) => ({\n ...res,\n version: exeVersion,\n })),\n stepMode: StepMode.Sync,\n },\n });\n\n const result = await exe.start();\n\n const resultHandlers: ExecutionResultHandlers<unknown> = {\n \"step-not-found\": () => {\n throw new Error(\n \"We should not get the result 'step-not-found' when checkpointing. This is a bug in the `inngest` SDK\",\n );\n },\n \"steps-found\": () => {\n throw new Error(\n \"We should not get the result 'steps-found' when checkpointing. This is a bug in the `inngest` SDK\",\n );\n },\n \"step-ran\": () => {\n throw new Error(\n \"We should not get the result 'step-ran' when checkpointing. This is a bug in the `inngest` SDK\",\n );\n },\n \"function-rejected\": (result) => {\n return actions.transformResponse(\"creating sync error response\", {\n status: result.retriable ? 500 : 400,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: result.retriable ? \"false\" : \"true\",\n ...(typeof result.retriable === \"string\"\n ? { [headerKeys.RetryAfter]: result.retriable }\n : {}),\n },\n version: exeVersion,\n body: stringify(undefinedToNull(result.error)),\n });\n },\n \"function-resolved\": ({ data }) => {\n // If the execution returned a Response (SSE streaming from the\n // engine, or a user-constructed Response in a durable endpoint),\n // pass it through directly — the headers and body are already set.\n if (data instanceof Response) {\n return data;\n }\n\n // Non-streaming path: plain return values from the function are\n // JSON-serialized and wrapped in a framework response.\n return actions.transformResponse(\"creating sync success response\", {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: exeVersion,\n body: stringify(undefinedToNull(data)),\n });\n },\n \"change-mode\": async ({ token }) => {\n switch (asyncMode) {\n case AsyncResponseType.Redirect: {\n let redirectUrl: string;\n\n if (asyncRedirectUrl) {\n if (typeof asyncRedirectUrl === \"function\") {\n // Full control: user provides complete URL\n redirectUrl = await asyncRedirectUrl({ runId, token });\n } else {\n // String path: resolve relative to request origin\n // new URL(\"/api/poll\", \"https://example.com\") → \"https://example.com/api/poll\"\n // new URL(\"https://other.com/poll\", \"https://example.com\") → \"https://other.com/poll\"\n const baseUrl = await actions.url(\"getting request origin\");\n const url = new URL(asyncRedirectUrl, baseUrl.origin);\n url.searchParams.set(\"runId\", runId);\n url.searchParams.set(\"token\", token);\n redirectUrl = url.toString();\n }\n } else {\n // Default: redirect to Inngest API\n redirectUrl = await this.client[\"inngestApi\"]\n [\"getTargetUrl\"](`/v1/http/runs/${runId}/output?token=${token}`)\n .then((url) => url.toString());\n }\n\n return actions.transformResponse(\n \"creating sync->async redirect response\",\n {\n status: 302,\n headers: {\n [headerKeys.Location]: redirectUrl,\n },\n version: exeVersion,\n body: \"\",\n },\n );\n }\n\n case AsyncResponseType.Token: {\n return actions.transformResponse(\n \"creating sync->async token response\",\n {\n status: 200,\n headers: {},\n version: exeVersion,\n body: stringify({ run_id: runId, token }),\n },\n );\n }\n\n default: {\n // TODO user-provided hook mate, incl. req args\n break;\n }\n }\n\n throw new Error(\"Not implemented: change-mode\");\n },\n };\n\n const resultHandler = resultHandlers[\n result.type\n ] as ExecutionResultHandler<unknown>;\n if (!resultHandler) {\n throw new Error(\n `No handler for execution result type: ${result.type}. This is a bug in the \\`inngest\\` SDK`,\n );\n }\n\n return resultHandler(result) as Awaited<Output>;\n }\n\n private async handleAsyncRequest({\n timer,\n actions,\n args,\n getHeaders,\n forceExecution,\n fns,\n }: {\n timer: ServerTiming;\n actions: HandlerResponseWithErrors;\n args: Input;\n getHeaders: () => Promise<Record<string, string>>;\n forceExecution?: boolean;\n fns?: InngestFunction.Any[];\n }): Promise<Awaited<Output>> {\n if (forceExecution && !actions.experimentalTransformSyncResponse) {\n throw new Error(\n \"This platform does not support async executions in Inngest for APIs.\",\n );\n }\n\n const methodP = actions.method(\"starting to handle request\");\n\n const [signature, method, body] = await Promise.all([\n actions\n .headers(\"checking signature for request\", headerKeys.Signature)\n .then((headerSignature) => {\n return headerSignature ?? undefined;\n }),\n methodP,\n methodP.then(async (method) => {\n if (method === \"POST\" || method === \"PUT\") {\n const body = await actions.body(\n `checking body for request signing as method is ${method}`,\n );\n if (!body) {\n // Empty body can happen with PUT requests\n return \"\";\n }\n // Some adapters return strings (req.text()), others return\n // pre-parsed objects (req.body). Handle both cases.\n if (typeof body === \"string\") {\n return JSON.parse(body);\n }\n return body;\n }\n\n return \"\";\n }),\n ]);\n\n const signatureValidation = this.validateSignature(signature, body);\n\n // Create middleware instances once; shared by wrapRequest and execution hooks.\n // Starts with client-level middleware; function-level middleware is appended\n // for POST requests once the target function is known.\n const mwInstances = this.client.middleware.map(\n (Cls) => new Cls({ client: this.client }),\n );\n\n /**\n * Prepares an action response by merging returned data to provide\n * trailing information such as `Server-Timing` headers.\n *\n * It should always prioritize the headers returned by the action, as they\n * may contain important information such as `Content-Type`.\n */\n const prepareActionRes = async (\n res: ActionResponse,\n ): Promise<ActionResponse> => {\n const headers: Record<string, string> = {\n ...(await getHeaders()),\n ...res.headers,\n ...(res.version === null\n ? {}\n : {\n [headerKeys.RequestVersion]: (\n res.version ?? PREFERRED_ASYNC_EXECUTION_VERSION\n ).toString(),\n }),\n };\n\n let signature: string | undefined;\n\n try {\n signature = await signatureValidation.then(async (result) => {\n if (!result.success || !result.keyUsed) {\n return undefined;\n }\n\n return await this.getResponseSignature(result.keyUsed, res.body);\n });\n } catch (err) {\n // If we fail to sign, retun a 500 with the error.\n return {\n ...res,\n headers,\n body: stringify(serializeError(err)),\n status: 500,\n };\n }\n\n if (signature) {\n headers[headerKeys.Signature] = signature;\n }\n\n return {\n ...res,\n headers,\n };\n };\n\n // Build the inner handler that wraps handleAction + prepareActionRes.\n // We capture `version` via closure so it can be passed to transformResponse.\n let actionResponseVersion: ExecutionVersion | null | undefined;\n\n const handleAndPrepare = async (): Promise<ActionResponse> => {\n const rawRes = await timer.wrap(\"action\", () =>\n this.handleAction({\n actions,\n timer,\n getHeaders,\n reqArgs: args,\n signatureValidation,\n body,\n method,\n forceExecution: Boolean(forceExecution),\n fns,\n mwInstances,\n }),\n );\n actionResponseVersion = rawRes.version;\n return prepareActionRes(rawRes);\n };\n\n // Only wrap POST requests with the wrapRequest middleware chain.\n // GET/PUT (introspection, registration) bypass the middleware.\n let chainResult: Promise<Middleware.Response>;\n if (method === \"POST\") {\n const url = await actions.url(\"building requestInfo for middleware\");\n\n // Append function-level middleware so it is scoped to this function only.\n const fnId = url.searchParams.get(queryKeys.FnId);\n const matchedFn = fnId ? this.fns[fnId] : undefined;\n const fnMw = matchedFn?.fn?.opts?.middleware ?? [];\n mwInstances.push(\n ...fnMw.map((Cls) => {\n return new Cls({ client: this.client });\n }),\n );\n\n const fn = matchedFn?.fn ?? null;\n\n const requestInfo: Middleware.Request = {\n headers: Object.freeze({ ...(await getHeaders()) }),\n method,\n url,\n body: () => Promise.resolve(body),\n };\n\n let runId = \"\";\n if (\n isRecord(body) &&\n isRecord(body.ctx) &&\n body.ctx.run_id &&\n typeof body.ctx.run_id === \"string\"\n ) {\n runId = body.ctx.run_id;\n }\n\n const innerHandler = async (): Promise<Middleware.Response> => {\n const prepared = await handleAndPrepare();\n return {\n status: prepared.status,\n headers: prepared.headers,\n body: prepared.body,\n };\n };\n\n const wrappedHandler = buildWrapRequestChain({\n fn,\n handler: innerHandler,\n middleware: mwInstances,\n requestArgs: args,\n requestInfo,\n runId,\n });\n\n // Start eagerly (matches prior behavior where handleAction starts before\n // the shouldStream check).\n chainResult = wrappedHandler();\n } else {\n chainResult = handleAndPrepare().then((prepared) => ({\n status: prepared.status,\n headers: prepared.headers,\n body: prepared.body,\n }));\n }\n\n // Attach error handling: if wrapRequest middleware throws, convert to 500.\n const safeChainResult = chainResult.catch(\n (err): Middleware.Response => ({\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n body: stringify({\n type: \"internal\",\n ...serializeError(err as Error),\n }),\n }),\n );\n\n let shouldStream: boolean;\n try {\n shouldStream = await this.shouldStream(actions);\n } catch (err) {\n return actions.transformResponse(\"sending back response\", {\n status: 500,\n headers: {\n ...(await getHeaders()),\n \"Content-Type\": \"application/json\",\n },\n body: stringify(serializeError(err)),\n version: undefined,\n });\n }\n\n if (shouldStream) {\n const method = await actions.method(\"starting streaming response\");\n\n if (method === \"POST\") {\n const { stream, finalize } = await createStream();\n\n /**\n * Errors are handled by `handleAction` here to ensure that an\n * appropriate response is always given.\n */\n void safeChainResult.then((res) => {\n return finalize(\n Promise.resolve({\n ...res,\n version: actionResponseVersion,\n }),\n );\n });\n\n return timer.wrap(\"res\", async () => {\n return actions.transformStreamingResponse?.(\n \"starting streaming response\",\n {\n status: 201,\n headers: await getHeaders(),\n body: stream,\n version: null,\n },\n );\n });\n }\n }\n\n return timer.wrap(\"res\", async () => {\n return safeChainResult.then((res) => {\n return actions.transformResponse(\"sending back response\", {\n ...res,\n version: actionResponseVersion,\n });\n });\n });\n }\n\n private async getActions(\n timer: ServerTiming,\n ...args: Input\n ): Promise<HandlerResponseWithErrors> {\n /**\n * Used for testing, allow setting action overrides externally when\n * calling the handler. Always search the final argument.\n */\n const lastArg = args[args.length - 1] as unknown;\n const actionOverrides =\n typeof lastArg === \"object\" &&\n lastArg !== null &&\n \"actionOverrides\" in lastArg &&\n typeof lastArg[\"actionOverrides\"] === \"object\" &&\n lastArg[\"actionOverrides\"] !== null\n ? lastArg[\"actionOverrides\"]\n : {};\n\n /**\n * We purposefully `await` the handler, as it could be either sync or\n * async.\n */\n const rawActions = {\n ...(await timer\n .wrap(\"handler\", () => this.handler(...args))\n .catch(rethrowError(\"Serve handler failed to run\"))),\n ...actionOverrides,\n };\n\n /**\n * Map over every `action` in `rawActions` and create a new `actions`\n * object where each function is safely promisified with each access\n * requiring a reason.\n *\n * This helps us provide high quality errors about what's going wrong for\n * each access without having to wrap every access in a try/catch.\n */\n const promisifiedActions: ActionHandlerResponseWithErrors = Object.entries(\n rawActions,\n ).reduce((acc, [key, value]) => {\n if (typeof value !== \"function\") {\n return acc;\n }\n\n return {\n ...acc,\n [key]: (reason: string, ...args: unknown[]) => {\n const errMessage = [\n `Failed calling \\`${key}\\` from serve handler`,\n reason,\n ]\n .filter(Boolean)\n .join(\" when \");\n\n const fn = () => (value as (...args: unknown[]) => unknown)(...args);\n\n return runAsPromise(fn)\n .catch(rethrowError(errMessage))\n .catch((err) => {\n this.client[internalLoggerSymbol].error({ err }, errMessage);\n throw err;\n });\n },\n };\n }, {} as ActionHandlerResponseWithErrors);\n\n /**\n * Mapped promisified handlers from userland `serve()` function mixed in\n * with some helpers.\n */\n const actions: HandlerResponseWithErrors = {\n ...promisifiedActions,\n queryStringWithDefaults: async (\n reason: string,\n key: string,\n ): Promise<string | undefined> => {\n const url = await actions.url(reason);\n\n const ret =\n (await actions.queryString?.(reason, key, url)) ||\n url.searchParams.get(key) ||\n undefined;\n\n return ret;\n },\n ...actionOverrides,\n };\n\n return actions;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: any fn\n private wrapHandler<THandler extends (...args: any[]) => any>(\n handler: THandler,\n ): THandler {\n /**\n * Some platforms check (at runtime) the length of the function being used\n * to handle an endpoint. If this is a variadic function, it will fail that\n * check.\n *\n * Therefore, we expect the arguments accepted to be the same length as the\n * `handler` function passed internally.\n *\n * We also set a name to avoid a common useless name in tracing such as\n * `\"anonymous\"` or `\"bound function\"`.\n *\n * https://github.com/getsentry/sentry-javascript/issues/3284\n */\n Object.defineProperties(handler, {\n name: {\n value: \"InngestHandler\",\n },\n length: {\n value: this.handler.length,\n },\n });\n\n return handler;\n }\n\n /**\n * Given a set of functions to check if an action is available from the\n * instance's handler, enact any action that is found.\n *\n * This method can fetch varying payloads of data, but ultimately is the place\n * where _decisions_ are made regarding functionality.\n *\n * For example, if we find that we should be viewing the UI, this function\n * will decide whether the UI should be visible based on the payload it has\n * found (e.g. env vars, options, etc).\n */\n private async handleAction({\n actions,\n timer,\n getHeaders,\n reqArgs,\n signatureValidation,\n body: rawBody,\n method,\n forceExecution,\n fns,\n mwInstances,\n }: {\n actions: HandlerResponseWithErrors;\n timer: ServerTiming;\n getHeaders: () => Promise<Record<string, string>>;\n reqArgs: unknown[];\n signatureValidation: ReturnType<InngestCommHandler[\"validateSignature\"]>;\n body: unknown;\n method: string;\n forceExecution: boolean;\n fns?: InngestFunction.Any[];\n mwInstances?: Middleware.BaseMiddleware[];\n }): Promise<ActionResponse> {\n if (!this.checkModeConfiguration()) {\n return internalServerErrorResponse;\n }\n\n // This is when the request body is completely missing. This commonly\n // happens when the HTTP framework doesn't have body parsing middleware,\n // or for PUT requests that don't require a body.\n const isMissingBody = !rawBody;\n let body = rawBody;\n\n try {\n let url = await actions.url(\"starting to handle request\");\n\n if (method === \"POST\" || forceExecution) {\n if (!forceExecution && isMissingBody) {\n this.client[internalLoggerSymbol].error(\n \"Missing body when executing, possibly due to missing request body middleware\",\n );\n\n return {\n status: 500,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(\n serializeError(\n new Error(\n \"Missing request body when executing, possibly due to missing request body middleware\",\n ),\n ),\n ),\n version: undefined,\n };\n }\n\n const validationResult = await signatureValidation;\n if (!validationResult.success) {\n return {\n status: 401,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(serializeError(validationResult.err)),\n version: undefined,\n };\n }\n\n let fn: { fn: InngestFunction.Any; onFailure: boolean } | undefined;\n let fnId: string | undefined;\n\n if (forceExecution) {\n fn =\n fns?.length && fns[0]\n ? { fn: fns[0], onFailure: false }\n : Object.values(this.fns)[0];\n fnId = fn?.fn.id();\n\n // Grab \"force step plan\" flag from headers\n let die = false;\n const dieHeader = await actions.headers(\n \"getting step plan force control for forced execution\",\n headerKeys.InngestForceStepPlan,\n );\n if (dieHeader) {\n const parsed = parseAsBoolean(dieHeader);\n if (typeof parsed === \"boolean\") {\n die = parsed;\n } else {\n this.client[internalLoggerSymbol].warn(\n { header: headerKeys.InngestForceStepPlan, value: dieHeader },\n \"Invalid boolean header value; defaulting to false\",\n );\n }\n }\n\n body = {\n event: {},\n events: [],\n steps: {},\n version: PREFERRED_ASYNC_EXECUTION_VERSION,\n sdkDecided: true,\n ctx: {\n attempt: 0,\n disable_immediate_execution: die,\n use_api: true,\n // This execution path doesn't control max attempts; it's already\n // been reported and Inngest is now in control of when to stop, so\n // we remove this restriction.\n max_attempts: Infinity,\n run_id: await actions.headers(\n \"getting run ID for forced execution\",\n headerKeys.InngestRunId,\n ),\n // TODO We need this to be given to us or the API to return it\n stack: { stack: [], current: 0 },\n },\n } as Extract<\n FnData,\n { version: typeof PREFERRED_ASYNC_EXECUTION_VERSION }\n >;\n } else {\n const rawProbe = await actions.queryStringWithDefaults(\n \"testing for probe\",\n queryKeys.Probe,\n );\n if (rawProbe) {\n const probe = enumFromValue(probeEnum, rawProbe);\n if (!probe) {\n // If we're here, we've received a probe that we don't recognize.\n // Fail.\n return {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(\n serializeError(new Error(`Unknown probe \"${rawProbe}\"`)),\n ),\n version: undefined,\n };\n }\n\n // Provide actions for every probe available.\n const probeActions: Record<\n probeEnum,\n () => MaybePromise<ActionResponse>\n > = {\n [probeEnum.Trust]: () => ({\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: \"\",\n version: undefined,\n }),\n };\n\n return probeActions[probe]();\n }\n\n fnId = await actions.queryStringWithDefaults(\n \"processing run request\",\n queryKeys.FnId,\n );\n if (!fnId) {\n throw new Error(\"No function ID found in async request\");\n }\n\n fn = this.fns[fnId];\n }\n\n if (typeof fnId === \"undefined\" || !fn) {\n throw new Error(\"No function ID found in request\");\n }\n\n // Always try and grab the step ID; in regular async flows this will be\n // in the querystring, and in sync modes it'll be in the headers.\n const stepId =\n (await actions.queryStringWithDefaults(\n \"processing run request\",\n queryKeys.StepId,\n )) ||\n (await actions.headers(\n \"processing run request\",\n headerKeys.InngestStepId,\n )) ||\n null;\n\n // Try get the request version from headers for sync executions.\n let headerReqVersion: ExecutionVersion | undefined;\n\n try {\n const rawVersionHeader = await actions.headers(\n \"processing run request\",\n headerKeys.RequestVersion,\n );\n\n // We only obey the request version header if it's actually a number,\n // even though the underlying schema allows more values; that schema\n // is intended to _always_ find a valid version and made for request\n // bodies.\n //\n // Note that the header will be a `string` at this point.\n if (rawVersionHeader && Number.isFinite(Number(rawVersionHeader))) {\n const res = createVersionSchema(\n this.client[internalLoggerSymbol],\n ).parse(Number(rawVersionHeader));\n\n if (!res.sdkDecided) {\n headerReqVersion = res.version;\n }\n }\n } catch {\n // no-op\n }\n\n const resolvedHeaders = await getHeaders();\n const { version, result } = this.runStep({\n functionId: fnId,\n data: body,\n stepId,\n timer,\n reqArgs,\n headers: resolvedHeaders,\n fn,\n forceExecution,\n actions,\n headerReqVersion,\n requestInfo: {\n headers: Object.freeze({ ...resolvedHeaders }),\n method,\n url,\n body: () => Promise.resolve(body),\n },\n mwInstances,\n });\n const stepOutput = await result;\n\n /**\n * Functions can return `undefined`, but we'll always convert this to\n * `null`, as this is appropriately serializable by JSON.\n */\n const opDataUndefinedToNull = (op: OutgoingOp) => {\n op.data = undefinedToNull(op.data);\n return op;\n };\n\n const resultHandlers: ExecutionResultHandlers<ActionResponse> = {\n \"function-rejected\": (result) => {\n return {\n status: result.retriable ? 500 : 400,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: result.retriable ? \"false\" : \"true\",\n ...(typeof result.retriable === \"string\"\n ? { [headerKeys.RetryAfter]: result.retriable }\n : {}),\n },\n body: stringify(undefinedToNull(result.error)),\n version,\n };\n },\n \"function-resolved\": (result) => {\n if (forceExecution) {\n const runCompleteOp: OutgoingOp = {\n id: _internals.hashId(\"complete\"),\n op: StepOpCode.RunComplete,\n data: undefinedToNull(result.data),\n };\n\n return {\n status: 206,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(runCompleteOp),\n version,\n };\n }\n\n return {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(undefinedToNull(result.data)),\n version,\n };\n },\n \"step-not-found\": (result) => {\n // we want to show the names and IDs of any steps that were found during the\n // run process\n const missingStepId = result.step.displayName || result.step.id;\n\n let error = `Could not find step \"${missingStepId}\" to run; timed out.`;\n\n if (result.foundSteps.length > 0) {\n const foundStepsSummary = result.foundSteps\n .map((step) => {\n const name = step.displayName || step.id;\n return `${name} (${step.id})`;\n })\n .join(\"\\n\");\n error = `${error} Found new steps: \\n${foundStepsSummary}.`;\n }\n\n if (result.totalFoundSteps > result.foundSteps.length) {\n error = `${error} (showing ${result.foundSteps.length} of ${result.totalFoundSteps})`;\n }\n\n return {\n status: 500,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: \"false\",\n },\n body: stringify({\n error,\n requestedStep: result.step.id,\n foundSteps: result.foundSteps,\n totalFoundSteps: result.totalFoundSteps,\n }),\n version,\n };\n },\n \"step-ran\": (result) => {\n const step = opDataUndefinedToNull(result.step);\n\n return {\n status: 206,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(typeof result.retriable !== \"undefined\"\n ? {\n [headerKeys.NoRetry]: result.retriable ? \"false\" : \"true\",\n ...(typeof result.retriable === \"string\"\n ? { [headerKeys.RetryAfter]: result.retriable }\n : {}),\n }\n : {}),\n },\n body: stringify([step]),\n version,\n };\n },\n \"steps-found\": (result) => {\n const steps = result.steps.map(opDataUndefinedToNull);\n\n return {\n status: 206,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(steps),\n version,\n };\n },\n \"change-mode\": (result) => {\n return {\n status: 500,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: \"true\",\n },\n body: stringify({\n error: `We wanted to change mode to \"${result.to}\", but this is not supported within the InngestCommHandler. This is a bug in the Inngest SDK.`,\n }),\n version,\n };\n },\n };\n\n const handler = resultHandlers[\n stepOutput.type\n ] as ExecutionResultHandler<ActionResponse>;\n\n try {\n return await handler(stepOutput);\n } catch (err) {\n this.client[internalLoggerSymbol].error(\n { err },\n \"Error handling execution result\",\n );\n throw err;\n }\n }\n\n // TODO: This feels hacky, so we should probably make it not hacky.\n const env = (await getHeaders())[headerKeys.Environment] ?? null;\n\n if (method === \"GET\") {\n return {\n status: 200,\n body: stringify(\n await this.introspectionBody({\n actions,\n env,\n signatureValidation,\n url,\n }),\n ),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n if (method === \"PUT\") {\n const [deployId, inBandSyncRequested] = await Promise.all([\n actions\n .queryStringWithDefaults(\n \"processing deployment request\",\n queryKeys.DeployId,\n )\n .then((deployId) => {\n return deployId === \"undefined\" ? undefined : deployId;\n }),\n\n Promise.resolve(\n parseAsBoolean(this.env[envKeys.InngestAllowInBandSync]),\n )\n .then((allowInBandSync) => {\n if (allowInBandSync !== undefined && !allowInBandSync) {\n return syncKind.OutOfBand;\n }\n\n return actions.headers(\n \"processing deployment request\",\n headerKeys.InngestSyncKind,\n );\n })\n .then((kind) => {\n return kind === syncKind.InBand;\n }),\n ]);\n\n if (inBandSyncRequested) {\n if (isMissingBody) {\n this.client[internalLoggerSymbol].error(\n \"Missing body when syncing, possibly due to missing request body middleware\",\n );\n\n return {\n status: 500,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(\n serializeError(\n new Error(\n \"Missing request body when syncing, possibly due to missing request body middleware\",\n ),\n ),\n ),\n version: undefined,\n };\n }\n\n // Validation can be successful if we're in dev mode and did not\n // actually validate a key. In this case, also check that we did indeed\n // use a particular key to validate.\n const sigCheck = await signatureValidation;\n\n if (!sigCheck.success) {\n return {\n status: 401,\n body: stringify({\n code: \"sig_verification_failed\",\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n const res = inBandSyncRequestBodySchema.safeParse(body);\n if (!res.success) {\n return {\n status: 400,\n body: stringify({\n code: \"invalid_request\",\n message: res.error.message,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n // We can trust the URL here because it's coming from\n // signature-verified request.\n url = this.reqUrl(new URL(res.data.url));\n\n // This should be an in-band sync\n const respBody = await this.inBandRegisterBody({\n actions,\n deployId,\n env,\n signatureValidation,\n url,\n });\n\n return {\n status: 200,\n body: stringify(respBody),\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.InngestSyncKind]: syncKind.InBand,\n },\n version: undefined,\n };\n }\n\n // If we're here, this is a legacy out-of-band sync\n const { status, message, modified } = await this.register(\n this.reqUrl(url),\n deployId,\n getHeaders,\n );\n\n return {\n status,\n body: stringify({ message, modified }),\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.InngestSyncKind]: syncKind.OutOfBand,\n },\n version: undefined,\n };\n }\n } catch (err) {\n return {\n status: 500,\n body: stringify({\n type: \"internal\",\n ...serializeError(err as Error),\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n this.client[internalLoggerSymbol].error(\n { method },\n \"Received unhandled HTTP method; expected POST, PUT, or GET\",\n );\n\n return {\n status: 405,\n body: JSON.stringify({\n message: `No action found; expected POST, PUT, or GET but received \"${method}\"`,\n mode: this.client.mode,\n }),\n headers: {},\n version: undefined,\n };\n }\n\n protected runStep({\n actions,\n functionId,\n stepId,\n data,\n timer,\n reqArgs,\n headers,\n fn,\n forceExecution,\n headerReqVersion,\n requestInfo,\n mwInstances,\n }: {\n actions: HandlerResponseWithErrors;\n functionId: string;\n stepId: string | null;\n data: unknown;\n timer: ServerTiming;\n reqArgs: unknown[];\n headers: Record<string, string>;\n fn: { fn: InngestFunction.Any; onFailure: boolean };\n forceExecution: boolean;\n headerReqVersion?: ExecutionVersion;\n requestInfo?: InngestExecutionOptions[\"requestInfo\"];\n mwInstances?: Middleware.BaseMiddleware[];\n }): { version: ExecutionVersion; result: Promise<ExecutionResult> } {\n if (!fn) {\n throw new Error(`Could not find function with ID \"${functionId}\"`);\n }\n\n // Try to get the request version from headers before falling back to\n // parsing it from the body.\n const immediateFnData = parseFnData(\n data,\n headerReqVersion,\n this.client[internalLoggerSymbol],\n );\n const { sdkDecided } = immediateFnData;\n let version = ExecutionVersion.V2;\n\n // Handle opting out of optimized parallelism\n if (\n version === ExecutionVersion.V2 &&\n sdkDecided &&\n fn.fn[\"shouldOptimizeParallelism\"]?.() === false\n ) {\n version = ExecutionVersion.V1;\n }\n\n const result = runAsPromise(async () => {\n const anyFnData = await fetchAllFnData({\n data: immediateFnData,\n api: this.client[\"inngestApi\"],\n logger: this.client[internalLoggerSymbol],\n });\n\n if (!anyFnData.ok) {\n throw new Error(anyFnData.error);\n }\n\n const createResponse =\n forceExecution && actions.experimentalTransformSyncResponse\n ? (data: unknown) =>\n actions.experimentalTransformSyncResponse!(\n \"created sync->async response\",\n data,\n ).then((res) => ({\n ...res,\n version,\n }))\n : undefined;\n\n const { event, events, steps, ctx } = anyFnData.value;\n\n const stepState = Object.entries(steps ?? {}).reduce<\n InngestExecutionOptions[\"stepState\"]\n >((acc, [id, result]) => {\n return {\n ...acc,\n [id]:\n result.type === \"data\"\n ? { id, data: result.data }\n : result.type === \"input\"\n ? { id, input: result.input }\n : { id, error: result.error },\n };\n }, {});\n\n const requestedRunStep =\n stepId === \"step\" ? undefined : stepId || undefined;\n\n const checkpointingConfig = fn.fn[\"shouldAsyncCheckpoint\"](\n requestedRunStep,\n ctx?.fn_id,\n Boolean(ctx?.disable_immediate_execution),\n this.defaultMaxRuntime,\n );\n\n const executionOptions: CreateExecutionOptions = {\n partialOptions: {\n client: this.client,\n runId: ctx?.run_id || \"\",\n stepMode: checkpointingConfig\n ? StepMode.AsyncCheckpointing\n : StepMode.Async,\n checkpointingConfig,\n data: {\n event: event as EventPayload,\n events: events as [EventPayload, ...EventPayload[]],\n runId: ctx?.run_id || \"\",\n attempt: ctx?.attempt ?? 0,\n maxAttempts: ctx?.max_attempts,\n },\n internalFnId: ctx?.fn_id,\n queueItemId: ctx?.qi_id,\n stepState,\n requestedRunStep,\n timer,\n isFailureHandler: fn.onFailure,\n disableImmediateExecution: ctx?.disable_immediate_execution,\n stepCompletionOrder: ctx?.stack?.stack ?? [],\n reqArgs,\n headers,\n createResponse,\n requestInfo,\n middlewareInstances: mwInstances,\n },\n };\n\n return fn.fn[\"createExecution\"](executionOptions).start();\n });\n\n return { version, result };\n }\n\n protected configs(url: URL): FunctionConfig[] {\n const configs = Object.values(this.rawFns).reduce<FunctionConfig[]>(\n (acc, fn) => [\n ...acc,\n ...fn[\"getConfig\"]({ baseUrl: url, appPrefix: this.client.id }),\n ],\n [],\n );\n\n for (const config of configs) {\n const check = functionConfigSchema.safeParse(config);\n if (!check.success) {\n const errors = check.error.errors.map((err) => err.message).join(\"; \");\n\n this.client[internalLoggerSymbol].warn(\n { functionId: config.id, errors },\n \"Invalid function config\",\n );\n }\n }\n\n return configs;\n }\n\n /**\n * Return an Inngest serve endpoint URL given a potential `path` and `host`.\n *\n * Will automatically use the `serveOrigin` and `servePath` if they have been\n * set when registering.\n */\n protected reqUrl(url: URL): URL {\n let ret = new URL(url);\n\n const servePath = this.servePath || this.env[envKeys.InngestServePath];\n\n if (servePath) {\n ret.pathname = servePath;\n }\n\n if (this.serveOrigin) {\n ret = new URL(ret.pathname + ret.search, this.serveOrigin);\n }\n\n return ret;\n }\n\n protected registerBody({\n url,\n deployId,\n }: {\n url: URL;\n\n /**\n * Non-optional to ensure we always consider if we have a deploy ID\n * available to us to use.\n */\n deployId: string | undefined | null;\n }): RegisterRequest {\n const body: RegisterRequest = {\n url: url.href,\n deployType: \"ping\",\n framework: this.frameworkName,\n appName: this.client.id,\n functions: this.configs(url),\n sdk: `js:v${version}`,\n v: \"0.1\",\n deployId: deployId || undefined,\n capabilities: {\n trust_probe: \"v1\",\n connect: \"v1\",\n },\n appVersion: this.client.appVersion,\n };\n\n return body;\n }\n\n protected async inBandRegisterBody({\n actions,\n deployId,\n env,\n signatureValidation,\n url,\n }: {\n actions: HandlerResponseWithErrors;\n\n /**\n * Non-optional to ensure we always consider if we have a deploy ID\n * available to us to use.\n */\n deployId: string | undefined | null;\n\n env: string | null;\n signatureValidation: ReturnType<InngestCommHandler[\"validateSignature\"]>;\n\n url: URL;\n }): Promise<InBandRegisterRequest> {\n const registerBody = this.registerBody({ deployId, url });\n const introspectionBody = await this.introspectionBody({\n actions,\n env,\n signatureValidation,\n url,\n });\n\n const body: InBandRegisterRequest = {\n app_id: this.client.id,\n appVersion: this.client.appVersion,\n capabilities: registerBody.capabilities,\n env,\n framework: registerBody.framework,\n functions: registerBody.functions,\n inspection: introspectionBody,\n platform: getPlatformName({\n ...getProcessEnv(),\n ...this.env,\n }),\n sdk_author: \"inngest\",\n sdk_language: \"\",\n sdk_version: \"\",\n sdk: registerBody.sdk,\n url: registerBody.url,\n };\n\n if (\n \"authentication_succeeded\" in introspectionBody &&\n introspectionBody.authentication_succeeded\n ) {\n body.sdk_language = introspectionBody.sdk_language;\n body.sdk_version = introspectionBody.sdk_version;\n }\n\n return body;\n }\n\n protected async introspectionBody({\n actions,\n env,\n signatureValidation,\n url,\n }: {\n actions: HandlerResponseWithErrors;\n env: string | null;\n signatureValidation: ReturnType<InngestCommHandler[\"validateSignature\"]>;\n url: URL;\n }): Promise<UnauthenticatedIntrospection | AuthenticatedIntrospection> {\n const registerBody = this.registerBody({\n url: this.reqUrl(url),\n deployId: null,\n });\n\n if (!this.client.mode) {\n throw new Error(\"No mode set; cannot introspect without mode\");\n }\n\n let introspection:\n | UnauthenticatedIntrospection\n | AuthenticatedIntrospection = {\n extra: {\n native_crypto: globalThis.crypto?.subtle ? true : false,\n },\n has_event_key: this.client[\"eventKeySet\"](),\n has_signing_key: Boolean(this.client.signingKey),\n function_count: registerBody.functions.length,\n mode: this.client.mode,\n schema_version: \"2024-05-24\",\n } satisfies UnauthenticatedIntrospection;\n\n // Only allow authenticated introspection in Cloud mode, since Dev mode skips\n // signature validation\n if (this.client.mode === \"cloud\") {\n try {\n const validationResult = await signatureValidation;\n if (!validationResult.success) {\n throw new Error(\"Signature validation failed\");\n }\n\n introspection = {\n ...introspection,\n authentication_succeeded: true,\n api_origin: this.client.apiBaseUrl,\n app_id: this.client.id,\n capabilities: {\n trust_probe: \"v1\",\n connect: \"v1\",\n },\n env,\n event_api_origin: this.client.eventBaseUrl,\n event_key_hash: this.hashedEventKey ?? null,\n extra: {\n ...introspection.extra,\n is_streaming: await this.shouldStream(actions),\n native_crypto: globalThis.crypto?.subtle ? true : false,\n },\n framework: this.frameworkName,\n sdk_language: \"js\",\n sdk_version: version,\n serve_origin: this.serveOrigin ?? null,\n serve_path: this.servePath ?? null,\n signing_key_fallback_hash: this.hashedSigningKeyFallback ?? null,\n signing_key_hash: this.hashedSigningKey ?? null,\n } satisfies AuthenticatedIntrospection;\n } catch {\n // Swallow signature validation error since we'll just return the\n // unauthenticated introspection\n introspection = {\n ...introspection,\n } satisfies UnauthenticatedIntrospection;\n }\n }\n\n return introspection;\n }\n\n protected async register(\n url: URL,\n deployId: string | undefined | null,\n getHeaders: () => Promise<Record<string, string>>,\n ): Promise<{ status: number; message: string; modified: boolean }> {\n const body = this.registerBody({ url, deployId });\n\n let res: globalThis.Response;\n\n // Clone the URL object to avoid mutating the property between requests.\n const registerUrl = new URL(this.inngestRegisterUrl.href);\n\n if (deployId) {\n registerUrl.searchParams.set(queryKeys.DeployId, deployId);\n }\n\n try {\n res = await fetchWithAuthFallback({\n authToken: this.hashedSigningKey,\n authTokenFallback: this.hashedSigningKeyFallback,\n fetch: this.client.fetch,\n url: registerUrl.href,\n options: {\n method: \"POST\",\n body: stringify(body),\n headers: {\n ...(await getHeaders()),\n [headerKeys.InngestSyncKind]: syncKind.OutOfBand,\n },\n redirect: \"follow\",\n },\n });\n } catch (err: unknown) {\n this.client[internalLoggerSymbol].error({ err }, \"Failed to register\");\n\n return {\n status: 500,\n message: `Failed to register${\n err instanceof Error ? `; ${err.message}` : \"\"\n }`,\n modified: false,\n };\n }\n\n const raw = await res.text();\n\n let data: z.input<typeof registerResSchema> = {};\n\n try {\n data = JSON.parse(raw);\n } catch (err) {\n this.client[internalLoggerSymbol].warn(\n { err },\n \"Couldn't unpack register response\",\n );\n\n let message = \"Failed to register\";\n if (err instanceof Error) {\n message += `; ${err.message}`;\n }\n message += `; status code: ${res.status}`;\n\n return {\n status: 500,\n message,\n modified: false,\n };\n }\n\n let status: number;\n let error: string;\n let skipped: boolean;\n let modified: boolean;\n try {\n ({ status, error, skipped, modified } = registerResSchema.parse(data));\n } catch (err) {\n this.client[internalLoggerSymbol].warn(\n { err },\n \"Invalid register response schema\",\n );\n\n let message = \"Failed to register\";\n if (err instanceof Error) {\n message += `; ${err.message}`;\n }\n message += `; status code: ${res.status}`;\n\n return {\n status: 500,\n message,\n modified: false,\n };\n }\n\n // The dev server polls this endpoint to register functions every few\n // seconds, but we only want to log that we've registered functions if\n // the function definitions change. Therefore, we compare the body sent\n // during registration with the body of the current functions and refuse\n // to register if the functions are the same.\n if (!skipped) {\n this.client[internalLoggerSymbol].debug(\"Registered inngest functions\");\n }\n\n return { status, message: error, modified };\n }\n\n /**\n * Check that the current mode has the configuration it requires.\n * Returns `true` if valid, `false` if not.\n */\n checkModeConfiguration(): boolean {\n this.client.setEnvVars(this.env);\n\n return checkModeConfiguration({\n mode: this.client.mode,\n signingKey: this.client.signingKey,\n internalLogger: this.client[internalLoggerSymbol],\n });\n }\n\n /**\n * Validate the signature of a request and return the signing key used to\n * validate it.\n */\n\n protected async validateSignature(\n sig: string | undefined,\n body: unknown,\n ): Promise<\n { success: true; keyUsed: string } | { success: false; err: Error }\n > {\n try {\n // Skip signature validation if requested (used by connect)\n if (this.skipSignatureValidation) {\n return { success: true, keyUsed: \"\" };\n }\n\n // Never validate signatures outside of prod. Make sure to check the mode\n // exists here instead of using nullish coalescing to confirm that the check\n // has been completed.\n if (this.client.mode !== \"cloud\") {\n return { success: true, keyUsed: \"\" };\n }\n\n // If we're here, we're in production; lack of a signing key is an error.\n if (!this.client.signingKey) {\n throw new Error(\n `No signing key found in client options or ${envKeys.InngestSigningKey} env var. Find your keys at https://app.inngest.com/env/production/manage/signing-key`,\n );\n }\n\n // If we're here, we're in production; lack of a req signature is an error.\n if (!sig) {\n throw new Error(`No ${headerKeys.Signature} provided`);\n }\n\n // Validate the signature\n return {\n success: true,\n keyUsed: await new RequestSignature(sig).verifySignature({\n body,\n allowExpiredSignatures: this.allowExpiredSignatures,\n signingKey: this.client.signingKey,\n signingKeyFallback: this.client.signingKeyFallback,\n logger: this.client[internalLoggerSymbol],\n }),\n };\n } catch (err) {\n return { success: false, err: err as Error };\n }\n }\n\n protected async getResponseSignature(\n key: string,\n body: string,\n ): Promise<string> {\n const now = Math.round(Date.now() / 1000);\n const mac = await signDataWithKey(\n body,\n key,\n now.toString(),\n this.client[internalLoggerSymbol],\n );\n\n return `t=${now}&s=${mac}`;\n }\n}\n\n/**\n * @internal Exported for testing; not part of the public API.\n */\nexport class RequestSignature {\n public timestamp: string;\n public signature: string;\n\n constructor(sig: string) {\n const params = new URLSearchParams(sig);\n this.timestamp = params.get(\"t\") || \"\";\n this.signature = params.get(\"s\") || \"\";\n\n if (!this.timestamp || !this.signature) {\n throw new Error(`Invalid ${headerKeys.Signature} provided`);\n }\n }\n\n private hasExpired(allowExpiredSignatures?: boolean) {\n if (allowExpiredSignatures) {\n return false;\n }\n\n const ts = Number.parseInt(this.timestamp, 10);\n if (!Number.isFinite(ts)) {\n return true;\n }\n\n const delta = Date.now() - ts * 1000;\n // Clamp both ends: negative delta (future-skewed `t`) would otherwise give\n // captured requests an unbounded replay\n return Math.abs(delta) > 1000 * 60 * 5;\n }\n\n async #verifySignature({\n body,\n signingKey,\n allowExpiredSignatures,\n logger,\n }: {\n body: unknown;\n signingKey: string;\n allowExpiredSignatures: boolean;\n logger: Logger;\n }): Promise<void> {\n if (this.hasExpired(allowExpiredSignatures)) {\n throw new Error(\"Signature has expired\");\n }\n\n const mac = await signDataWithKey(body, signingKey, this.timestamp, logger);\n if (!timingSafeEqual(mac, this.signature)) {\n throw new Error(\"Invalid signature\");\n }\n }\n\n public async verifySignature({\n body,\n signingKey,\n signingKeyFallback,\n allowExpiredSignatures,\n logger,\n }: {\n body: unknown;\n signingKey: string;\n signingKeyFallback: string | undefined;\n allowExpiredSignatures: boolean;\n logger: Logger;\n }): Promise<string> {\n try {\n await this.#verifySignature({\n body,\n signingKey,\n allowExpiredSignatures,\n logger,\n });\n\n return signingKey;\n } catch (err) {\n if (!signingKeyFallback) {\n throw err;\n }\n\n await this.#verifySignature({\n body,\n signingKey: signingKeyFallback,\n allowExpiredSignatures,\n logger,\n });\n\n return signingKeyFallback;\n }\n }\n}\n\n/**\n * The broad definition of a handler passed when instantiating an\n * {@link InngestCommHandler} instance.\n */\nexport type Handler<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Input extends any[] = any[],\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Output = any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n StreamOutput = any,\n> = (...args: Input) => HandlerResponse<Output, StreamOutput>;\n\n// biome-ignore lint/suspicious/noExplicitAny: intentional\nexport type HandlerResponse<Output = any, StreamOutput = any> = {\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n body: () => MaybePromise<any>;\n env?: () => MaybePromise<Env | undefined>;\n headers: (key: string) => MaybePromise<string | null | undefined>;\n\n method: () => MaybePromise<string>;\n queryString?: (\n key: string,\n url: URL,\n ) => MaybePromise<string | null | undefined>;\n url: () => MaybePromise<URL>;\n\n /**\n * The `transformResponse` function receives the output of the Inngest SDK and\n * can decide how to package up that information to appropriately return the\n * information to Inngest.\n *\n * Mostly, this is taking the given parameters and returning a new `Response`.\n *\n * The function is passed an {@link ActionResponse}, an object containing a\n * `status` code, a `headers` object, and a stringified `body`. This ensures\n * you can appropriately handle the response, including use of any required\n * parameters such as `res` in Express-/Connect-like frameworks.\n */\n transformResponse: (res: ActionResponse<string>) => Output;\n\n /**\n * The `transformStreamingResponse` function, if defined, declares that this\n * handler supports streaming responses back to Inngest. This is useful for\n * functions that are expected to take a long time, as edge streaming can\n * often circumvent restrictive request timeouts and other limitations.\n *\n * If your handler does not support streaming, do not define this function.\n *\n * It receives the output of the Inngest SDK and can decide how to package\n * up that information to appropriately return the information in a stream\n * to Inngest.\n *\n * Mostly, this is taking the given parameters and returning a new `Response`.\n *\n * The function is passed an {@link ActionResponse}, an object containing a\n * `status` code, a `headers` object, and `body`, a `ReadableStream`. This\n * ensures you can appropriately handle the response, including use of any\n * required parameters such as `res` in Express-/Connect-like frameworks.\n */\n transformStreamingResponse?: (\n res: ActionResponse<ReadableStream>,\n ) => StreamOutput;\n\n /**\n * TODO Needed to give folks a chance to wrap arguments if they need to in\n * order to extract the request body so that it can be sent back to Inngest\n * during either sync or async calls.\n *\n * This is because usually they do not interact directly with e.g. the\n * `Response` object, but with sync mode they do, so we need to provide hooks\n * to let us access the body.\n */\n experimentalTransformSyncRequest?: (\n ...args: unknown[]\n ) => MaybePromise<unknown>;\n\n /**\n * TODO Needed to give folks a chance to transform the response from their own\n * code to an Inngestish response. This is only needed so that sync mode can\n * checkpoint the response if we've gone through the entire run with no\n * interruptions.\n *\n * Because of its location when being specified, we have scoped access to the\n * `reqArgs` (e.g. `req` and `res`), so we don't need to pass them here.\n */\n experimentalTransformSyncResponse?: (\n data: unknown,\n ) => MaybePromise<Omit<ActionResponse, \"version\">>;\n};\n\n/**\n * The response from the Inngest SDK before it is transformed in to a\n * framework-compatible response by an {@link InngestCommHandler} instance.\n */\nexport interface ActionResponse<\n TBody extends string | ReadableStream = string,\n> {\n /**\n * The HTTP status code to return.\n */\n status: number;\n\n /**\n * The headers to return in the response.\n */\n headers: Record<string, string>;\n\n /**\n * A stringified body to return.\n */\n body: TBody;\n\n /**\n * The version of the execution engine that was used to run this action.\n *\n * If the action didn't use the execution engine (for example, a GET request\n * as a health check) or would have but errored before reaching it, this will\n * be `undefined`.\n *\n * If the version should be entirely omitted from the response (for example,\n * when sending preliminary headers when streaming), this will be `null`.\n */\n version: ExecutionVersion | null | undefined;\n}\n\n/**\n * A version of {@link HandlerResponse} where each function is safely\n * promisified and requires a reason for each access.\n *\n * This enables us to provide accurate errors for each access without having to\n * wrap every access in a try/catch.\n */\nexport type ActionHandlerResponseWithErrors = {\n [K in keyof HandlerResponse]: NonNullable<HandlerResponse[K]> extends (\n ...args: infer Args\n ) => infer R\n ? R extends MaybePromise<infer PR>\n ? (errMessage: string, ...args: Args) => Promise<PR>\n : (errMessage: string, ...args: Args) => Promise<R>\n : HandlerResponse[K];\n};\n\n/**\n * A version of {@link ActionHandlerResponseWithErrors} that includes helper\n * functions that provide sensible defaults on top of the direct access given\n * from the bare response.\n */\nexport interface HandlerResponseWithErrors\n extends ActionHandlerResponseWithErrors {\n /**\n * Fetch a query string value from the request. If no `querystring` action has\n * been provided by the `serve()` handler, this will fall back to using the\n * provided URL present in the request to parse the query string from instead.\n */\n queryStringWithDefaults: (\n reason: string,\n key: string,\n ) => Promise<string | undefined>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"InngestCommHandler.js","names":["acc","defaultStreamingOption: typeof this.streaming","v","body","result","redirectUrl: string","method","headers: Record<string, string>","signature: string | undefined","signature","actionResponseVersion: ExecutionVersion | null | undefined","filteredHeaders: Record<string, string>","chainResult: Promise<Middleware.Response>","requestInfo: Middleware.Request","shouldStream: boolean","actions: HandlerResponseWithErrors","args","fn: { fn: InngestFunction.Any; onFailure: boolean } | undefined","fnId: string | undefined","probe","probeEnum","headerReqVersion: ExecutionVersion | undefined","runCompleteOp: OutgoingOp","deployId","version","data","executionOptions: CreateExecutionOptions","body: InBandRegisterRequest","introspection:\n | UnauthenticatedIntrospection\n | AuthenticatedIntrospection","signingKeyHash: string | null","signingKeyFallbackHash: string | null","res: globalThis.Response","err: unknown","data: z.input<typeof registerResSchema>","status: number","error: string","skipped: boolean","modified: boolean","#verifySignature"],"sources":["../../src/components/InngestCommHandler.ts"],"sourcesContent":["import { z } from \"zod/v3\";\nimport {\n defaultMaxRetries,\n ExecutionVersion,\n envKeys,\n forwardedHeaders,\n headerKeys,\n internalEvents,\n logPrefix,\n probe as probeEnum,\n queryKeys,\n syncKind,\n} from \"../helpers/consts.ts\";\nimport { enumFromValue } from \"../helpers/enum.ts\";\nimport {\n checkModeConfiguration,\n type Env,\n getPlatformName,\n getProcessEnv,\n inngestHeaders,\n parseAsBoolean,\n protectEnv,\n} from \"../helpers/env.ts\";\nimport { rethrowError, serializeError } from \"../helpers/errors.ts\";\nimport {\n createVersionSchema,\n type FnData,\n fetchAllFnData,\n parseFnData,\n undefinedToNull,\n} from \"../helpers/functions.ts\";\nimport { warnOnce } from \"../helpers/log.ts\";\nimport { fetchWithAuthFallback, signDataWithKey } from \"../helpers/net.ts\";\nimport { runAsPromise } from \"../helpers/promises.ts\";\nimport { ServerTiming } from \"../helpers/ServerTiming.ts\";\nimport { createStream } from \"../helpers/stream.ts\";\nimport {\n hashEventKey,\n hashSigningKey,\n removeSigningKeyPrefix,\n stringify,\n timingSafeEqual,\n} from \"../helpers/strings.ts\";\nimport { isRecord, type MaybePromise } from \"../helpers/types.ts\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport {\n type APIStepPayload,\n AsyncResponseType,\n type AsyncResponseValue,\n type AuthenticatedIntrospection,\n DefaultMaxRuntime,\n type EventPayload,\n type FunctionConfig,\n functionConfigSchema,\n type InBandRegisterRequest,\n inBandSyncRequestBodySchema,\n type OutgoingOp,\n type RegisterOptions,\n type RegisterRequest,\n StepMode,\n StepOpCode,\n type UnauthenticatedIntrospection,\n} from \"../types.ts\";\nimport { version } from \"../version.ts\";\nimport { getAsyncCtx } from \"./execution/als.ts\";\nimport { _internals } from \"./execution/engine.ts\";\nimport {\n type ExecutionResult,\n type ExecutionResultHandler,\n type ExecutionResultHandlers,\n type InngestExecutionOptions,\n PREFERRED_ASYNC_EXECUTION_VERSION,\n} from \"./execution/InngestExecution.ts\";\nimport { type Inngest, internalLoggerSymbol } from \"./Inngest.ts\";\nimport {\n type CreateExecutionOptions,\n InngestFunction,\n} from \"./InngestFunction.ts\";\nimport { buildWrapRequestChain, type Middleware } from \"./middleware/index.ts\";\n\n// A response object for when an internal server error occurs. When that\n// happens, we don't to leak any internal details to the client.\nconst internalServerErrorResponse = {\n body: stringify({ code: \"internal_server_error\" }),\n headers: { \"Content-Type\": \"application/json\" },\n status: 500,\n version: undefined,\n} as const;\n\n/**\n * A set of options that can be passed to a serve handler, intended to be used\n * by internal and custom serve handlers to provide a consistent interface.\n *\n * @public\n */\nexport interface ServeHandlerOptions extends RegisterOptions {\n /**\n * The `Inngest` instance used to declare all functions.\n */\n client: Inngest.Like;\n\n /**\n * An array of the functions to serve and register with Inngest.\n */\n functions: readonly InngestFunction.Like[];\n}\n\n/**\n * Parameters passed to the asyncRedirectUrl function.\n */\nexport interface AsyncRedirectUrlParams {\n /**\n * The unique identifier for this run.\n */\n runId: string;\n\n /**\n * The token used to authenticate the request to fetch run output.\n */\n token: string;\n}\n\nexport interface SyncHandlerOptions extends RegisterOptions {\n /**\n * The `Inngest` instance used to declare all functions.\n */\n client: Inngest.Like;\n\n /**\n * The type of response you wish to return to an API endpoint when using steps\n * within it and we must transition to {@link StepMode.Async}.\n *\n * In most cases, this defaults to {@link AsyncResponseType.Redirect}.\n */\n asyncResponse?: AsyncResponseValue;\n\n /**\n * Custom URL to redirect to when switching from sync to async mode.\n *\n * Can be:\n * - A string path (e.g., \"/api/inngest/poll\") - resolved relative to request origin\n * - A function that receives `{ runId, token }` and returns a full URL\n *\n * When a string path is provided, `runId` and `token` query parameters are\n * automatically appended.\n *\n * @example\n * ```ts\n * // String path - resolved relative to request origin\n * asyncRedirectUrl: \"/api/inngest/poll\"\n *\n * // Function - full control over URL construction\n * asyncRedirectUrl: ({ runId, token }) =>\n * `https://my-app.com/poll?run=${runId}&t=${token}`\n * ```\n */\n asyncRedirectUrl?:\n | string\n | ((params: AsyncRedirectUrlParams) => string | Promise<string>);\n\n /**\n * If defined, this sets the function ID that represents this endpoint.\n * Without this set, it defaults to using the detected method and path of the\n * request, for example: `GET /api/my-endpoint`.\n */\n functionId?: string;\n\n /**\n * Specifies the maximum number of retries for all steps.\n *\n * Can be a number from `0` to `20`. Defaults to `3`.\n */\n retries?:\n | 0\n | 1\n | 2\n | 3\n | 4\n | 5\n | 6\n | 7\n | 8\n | 9\n | 10\n | 11\n | 12\n | 13\n | 14\n | 15\n | 16\n | 17\n | 18\n | 19\n | 20;\n}\n\nexport type SyncAdapterOptions = Omit<SyncHandlerOptions, \"client\">;\n\nexport interface InternalServeHandlerOptions extends ServeHandlerOptions {\n /**\n * Can be used to override the framework name given to a particular serve\n * handler.\n */\n frameworkName?: string;\n\n /**\n * Can be used to force the handler to always execute functions regardless of\n * the request method or other factors.\n *\n * This is primarily intended for use with Inngest in APIs, where requests may\n * not have the usual shape of an Inngest payload, but we want to pull data\n * and execute.\n */\n // forceExecution?: boolean;\n}\n\ninterface InngestCommHandlerOptions<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Input extends any[] = any[],\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Output = any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n StreamOutput = any,\n> extends RegisterOptions {\n /**\n * The name of the framework this handler is designed for. Should be\n * lowercase, alphanumeric characters inclusive of `-` and `/`.\n *\n * This should never be defined by the user; a {@link ServeHandler} should\n * abstract this.\n */\n frameworkName: string;\n\n /**\n * The name of this serve handler, e.g. `\"My App\"`. It's recommended that this\n * value represents the overarching app/service that this set of functions is\n * being served from.\n *\n * This can also be an `Inngest` client, in which case the name given when\n * instantiating the client is used. This is useful if you're sending and\n * receiving events from the same service, as you can reuse a single\n * definition of Inngest.\n */\n client: Inngest.Like;\n\n /**\n * An array of the functions to serve and register with Inngest.\n */\n functions?: readonly InngestFunction.Like[];\n\n /**\n * The `handler` is the function that will be called with your framework's\n * request arguments and returns a set of functions that the SDK will use to\n * access various parts of the request, such as the body, headers, and query\n * string parameters.\n *\n * It also defines how to transform a response from the SDK into a response\n * that your framework can understand, ensuring headers, status codes, and\n * body are all set correctly.\n *\n * @example\n * ```ts\n * function handler (req: Request, res: Response) {\n * return {\n * method: () => req.method,\n * body: () => req.json(),\n * headers: (key) => req.headers.get(key),\n * url: () => req.url,\n * transformResponse: ({ body, headers, status }) => {\n * return new Response(body, { status, headers });\n * },\n * };\n * };\n * ```\n *\n * See any existing handler for a full example.\n */\n handler: Handler<Input, Output, StreamOutput>;\n\n skipSignatureValidation?: boolean;\n\n /**\n * The default `maxRuntime` in milliseconds to use for checkpointing when the\n * user hasn't explicitly configured one at the function or client level.\n *\n * Defaults to {@link DefaultMaxRuntime.serve} (10 seconds).\n */\n defaultMaxRuntime?: DefaultMaxRuntime;\n\n /**\n * Options for when this comm handler executes a synchronous (API) function.\n */\n syncOptions?: SyncHandlerOptions;\n}\n\n/**\n * A schema for the response from Inngest when registering.\n */\nconst registerResSchema = z.object({\n status: z.number().default(200),\n skipped: z.boolean().optional().default(false),\n modified: z.boolean().optional().default(false),\n error: z.string().default(\"Successfully registered\"),\n});\n\n/**\n * `InngestCommHandler` is a class for handling incoming requests from Inngest (or\n * Inngest's tooling such as the dev server or CLI) and taking appropriate\n * action for any served functions.\n *\n * All handlers (Next.js, RedwoodJS, Remix, Deno Fresh, etc.) are created using\n * this class; the exposed `serve` function will - most commonly - create an\n * instance of `InngestCommHandler` and then return `instance.createHandler()`.\n *\n * See individual parameter details for more information, or see the\n * source code for an existing handler, e.g.\n * {@link https://github.com/inngest/inngest-js/blob/main/src/next.ts}\n *\n * @example\n * ```\n * // my-custom-handler.ts\n * import {\n * InngestCommHandler,\n * type ServeHandlerOptions,\n * } from \"./components/InngestCommHandler\";\n *\n * export const serve = (options: ServeHandlerOptions) => {\n * const handler = new InngestCommHandler({\n * frameworkName: \"my-custom-handler\",\n * ...options,\n * handler: (req: Request) => {\n * return {\n * body: () => req.json(),\n * headers: (key) => req.headers.get(key),\n * method: () => req.method,\n * url: () => new URL(req.url, `https://${req.headers.get(\"host\") || \"\"}`),\n * transformResponse: ({ body, status, headers }) => {\n * return new Response(body, { status, headers });\n * },\n * };\n * },\n * });\n *\n * return handler.createHandler();\n * };\n * ```\n *\n * @public\n */\nexport class InngestCommHandler<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Input extends any[] = any[],\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Output = any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n StreamOutput = any,\n> {\n /**\n * The handler specified during instantiation of the class.\n */\n public readonly handler: Handler;\n\n /**\n * The URL of the Inngest function registration endpoint.\n */\n private readonly inngestRegisterUrl: URL;\n\n /**\n * The name of the framework this handler is designed for. Should be\n * lowercase, alphanumeric characters inclusive of `-` and `/`.\n */\n protected readonly frameworkName: string;\n\n /**\n * The origin used to access the Inngest serve endpoint, e.g.:\n *\n * \"https://myapp.com\" or \"https://myapp.com:1234\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom origin here to ensure that the path is reported\n * correctly when registering functions with Inngest.\n *\n * To also provide a custom path, use `servePath`.\n */\n private readonly _serveOrigin: string | undefined;\n\n /**\n * The path to the Inngest serve endpoint. e.g.:\n *\n * \"/some/long/path/to/inngest/endpoint\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom path (excluding the hostname) here to ensure that the\n * path is reported correctly when registering functions with Inngest.\n *\n * To also provide a custom hostname, use `serveOrigin`.\n */\n private readonly _servePath: string | undefined;\n\n protected readonly streaming: RegisterOptions[\"streaming\"];\n\n /**\n * A private collection of just Inngest functions, as they have been passed\n * when instantiating the class.\n */\n private readonly rawFns: InngestFunction.Any[];\n\n private readonly client: Inngest.Any;\n\n /**\n * A private collection of functions that are being served. This map is used\n * to find and register functions when interacting with Inngest Cloud.\n */\n private readonly fns: Record<\n string,\n { fn: InngestFunction.Any; onFailure: boolean }\n > = {};\n\n private env: Env = getProcessEnv();\n\n private allowExpiredSignatures: boolean;\n\n private readonly _options: InngestCommHandlerOptions<\n Input,\n Output,\n StreamOutput\n >;\n\n private readonly skipSignatureValidation: boolean;\n\n private readonly defaultMaxRuntime: DefaultMaxRuntime;\n\n constructor(options: InngestCommHandlerOptions<Input, Output, StreamOutput>) {\n // Set input options directly so we can reference them later\n this._options = options;\n\n /**\n * v2 -> v3 migration error.\n * TODO: do we need to handle people going from v2->v4?\n *\n * If a serve handler is passed a client as the first argument, it'll be\n * spread in to these options. We should be able to detect this by picking\n * up a unique property on the object.\n */\n if (Object.hasOwn(options, \"eventKey\")) {\n throw new Error(\n `${logPrefix} You've passed an Inngest client as the first argument to your serve handler. This is no longer supported in v3; please pass the Inngest client as the \\`client\\` property of an options object instead. See https://www.inngest.com/docs/sdk/migration`,\n );\n }\n\n this.frameworkName = options.frameworkName;\n this.client = options.client as Inngest.Any;\n this.defaultMaxRuntime =\n options.defaultMaxRuntime ?? DefaultMaxRuntime.serve;\n\n this.handler = options.handler as Handler;\n\n /**\n * Provide a hidden option to allow expired signatures to be accepted during\n * testing.\n */\n this.allowExpiredSignatures = Boolean(\n // biome-ignore lint/complexity/noArguments: intentional\n arguments[\"0\"]?.__testingAllowExpiredSignatures,\n );\n\n // Ensure we filter any undefined functions in case of missing imports.\n this.rawFns = (options.functions?.filter(Boolean) ??\n []) as InngestFunction.Any[];\n\n if (this.rawFns.length !== (options.functions ?? []).length) {\n this.client[internalLoggerSymbol].warn(\n `Some functions passed to serve() are undefined and misconfigured. Please check your imports.`,\n );\n }\n\n this.fns = this.rawFns.reduce<\n Record<string, { fn: InngestFunction.Any; onFailure: boolean }>\n >((acc, fn) => {\n const configs = fn[\"getConfig\"]({\n baseUrl: new URL(\"https://example.com\"),\n appPrefix: this.client.id,\n });\n\n const fns = configs.reduce((acc, { id }, index) => {\n return { ...acc, [id]: { fn, onFailure: Boolean(index) } };\n }, {});\n\n // biome-ignore lint/complexity/noForEach: intentional\n configs.forEach(({ id }) => {\n if (acc[id]) {\n throw new Error(\n `Duplicate function ID \"${id}\"; please change a function's name or provide an explicit ID to avoid conflicts.`,\n );\n }\n });\n\n return {\n ...acc,\n ...fns,\n };\n }, {});\n\n this.inngestRegisterUrl = new URL(\"/fn/register\", this.client.apiBaseUrl);\n\n this._serveOrigin =\n options.serveOrigin || this.env[envKeys.InngestServeOrigin];\n this._servePath = options.servePath || this.env[envKeys.InngestServePath];\n\n this.skipSignatureValidation = options.skipSignatureValidation || false;\n\n const defaultStreamingOption: typeof this.streaming = false;\n this.streaming = z\n .boolean()\n .default(defaultStreamingOption)\n .catch((ctx) => {\n this.client[internalLoggerSymbol].warn(\n { input: ctx.input, default: defaultStreamingOption },\n \"Unknown streaming option; using default\",\n );\n\n return defaultStreamingOption;\n })\n .parse(\n options.streaming || parseAsBoolean(this.env[envKeys.InngestStreaming]),\n );\n\n // Early validation for environments where process.env is available (Node.js).\n // Edge environments will skip this and validate at request time instead.\n this.client.setEnvVars(this.env);\n }\n\n /**\n * The origin used to access the Inngest serve endpoint, e.g.:\n *\n * \"https://myapp.com\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom origin here to ensure that the path is reported\n * correctly when registering functions with Inngest.\n *\n * To also provide a custom path, use `servePath`.\n */\n protected get serveOrigin(): string | undefined {\n if (this._serveOrigin) {\n return this._serveOrigin;\n }\n\n const envOrigin = this.env[envKeys.InngestServeOrigin];\n if (envOrigin) {\n return envOrigin;\n }\n\n const envHost = this.env[envKeys.InngestServeHost];\n if (envHost) {\n warnOnce(\n this.client[internalLoggerSymbol],\n \"serve-host-deprecated\",\n \"INNGEST_SERVE_HOST is deprecated; use INNGEST_SERVE_ORIGIN instead\",\n );\n return envHost;\n }\n\n return undefined;\n }\n\n /**\n * The path to the Inngest serve endpoint. e.g.:\n *\n * \"/some/long/path/to/inngest/endpoint\"\n *\n * By default, the library will try to infer this using request details such\n * as the \"Host\" header and request path, but sometimes this isn't possible\n * (e.g. when running in a more controlled environments such as AWS Lambda or\n * when dealing with proxies/redirects).\n *\n * Provide the custom path (excluding the hostname) here to ensure that the\n * path is reported correctly when registering functions with Inngest.\n *\n * To also provide a custom hostname, use `serveOrigin`.\n *\n * This is a getter to encourage checking the environment for the serve path\n * each time it's accessed, as it may change during execution.\n */\n protected get servePath(): string | undefined {\n return this._servePath || this.env[envKeys.InngestServePath];\n }\n\n private get hashedEventKey(): string | undefined {\n if (!this.client.eventKey) {\n return undefined;\n }\n return hashEventKey(this.client.eventKey);\n }\n\n // hashedSigningKey creates a sha256 checksum of the signing key with the\n // same signing key prefix.\n private get hashedSigningKey(): string | undefined {\n if (!this.client.signingKey) {\n return undefined;\n }\n return hashSigningKey(this.client.signingKey);\n }\n\n private get hashedSigningKeyFallback(): string | undefined {\n if (!this.client.signingKeyFallback) {\n return undefined;\n }\n return hashSigningKey(this.client.signingKeyFallback);\n }\n\n /**\n * Returns a `boolean` representing whether this handler will stream responses\n * or not. Takes into account the user's preference and the platform's\n * capabilities.\n */\n private async shouldStream(\n actions: HandlerResponseWithErrors,\n ): Promise<boolean> {\n const rawProbe = await actions.queryStringWithDefaults(\n \"testing for probe\",\n queryKeys.Probe,\n );\n if (rawProbe !== undefined) {\n return false;\n }\n\n const envStreaming = this.env[envKeys.InngestStreaming];\n if (envStreaming === \"allow\" || envStreaming === \"force\") {\n warnOnce(\n this.client[internalLoggerSymbol],\n \"streaming-allow-force-deprecated\",\n { value: envStreaming },\n `INNGEST_STREAMING=\"${envStreaming}\" is deprecated; set INNGEST_STREAMING=true instead`,\n );\n }\n\n const streamingRequested =\n this.streaming === true ||\n parseAsBoolean(this.env[envKeys.InngestStreaming]) === true ||\n envStreaming === \"allow\" ||\n envStreaming === \"force\";\n\n // We must be able to stream responses to continue.\n if (!actions.transformStreamingResponse) {\n if (streamingRequested) {\n throw new Error(\n `${logPrefix} Streaming has been forced but the serve handler does not support streaming. Please either remove the streaming option or use a serve handler that supports streaming.`,\n );\n }\n return false;\n }\n\n return streamingRequested;\n }\n\n private async isInngestReq(\n actions: HandlerResponseWithErrors,\n ): Promise<boolean> {\n const reqMessage = `checking if this is an Inngest request`;\n\n const [runId, signature] = await Promise.all([\n actions.headers(reqMessage, headerKeys.InngestRunId),\n actions.headers(reqMessage, headerKeys.Signature),\n ]);\n\n // Note that the signature just has to be present; in Dev it'll be empty,\n // but still set to `\"\"`.\n return Boolean(runId && typeof signature === \"string\");\n }\n\n /**\n * Start handling a request, setting up environments, modes, and returning\n * some helpers.\n */\n private async initRequest(...args: Input): Promise<{\n timer: ServerTiming;\n actions: HandlerResponseWithErrors;\n getHeaders: () => Promise<Record<string, string>>;\n }> {\n const timer = new ServerTiming(this.client[internalLoggerSymbol]);\n const actions = await this.getActions(timer, ...args);\n\n const [env, expectedServerKind] = await Promise.all([\n actions.env?.(\"starting to handle request\"),\n actions.headers(\n \"checking expected server kind\",\n headerKeys.InngestServerKind,\n ),\n ]);\n\n // Always make sure to merge whatever env we've been given with\n // `process.env`; some platforms may not provide all the necessary\n // environment variables or may use two sources.\n // Update both handler's env and client's env to ensure consistency.\n this.env = protectEnv({ ...getProcessEnv(), ...env });\n this.client.setEnvVars(this.env);\n\n const headerPromises = forwardedHeaders.map(async (header) => {\n const value = await actions.headers(\n `fetching ${header} for forwarding`,\n header,\n );\n\n return { header, value };\n });\n\n const headersToForwardP = Promise.all(headerPromises).then(\n (fetchedHeaders) => {\n return fetchedHeaders.reduce<Record<string, string>>(\n (acc, { header, value }) => {\n if (value) {\n acc[header] = value;\n }\n\n return acc;\n },\n {},\n );\n },\n );\n\n const getHeaders = async (): Promise<Record<string, string>> => ({\n ...inngestHeaders({\n env: this.env,\n framework: this.frameworkName,\n client: this.client,\n expectedServerKind: expectedServerKind || undefined,\n extras: {\n \"Server-Timing\": timer.getHeader(),\n },\n }),\n ...(await headersToForwardP),\n });\n\n return {\n timer,\n actions,\n getHeaders,\n };\n }\n\n /**\n * `createSyncHandler` should be used to return a type-equivalent version of\n * the `handler` specified during instantiation.\n */\n public createSyncHandler<\n THandler extends (...args: Input) => Promise<Awaited<Output>>,\n >(): (handler: THandler) => THandler {\n // Return a function that can be used to wrap endpoints\n return (handler) => {\n return this.wrapHandler((async (...args) => {\n const reqInit = await this.initRequest(...args);\n\n const fn = new InngestFunction(\n this.client,\n {\n id: this._options.syncOptions?.functionId ?? \"\",\n retries: this._options.syncOptions?.retries ?? defaultMaxRetries,\n },\n () => handler(...args),\n );\n\n // Decide if this request looks like an Inngest request. If it does,\n // we'll just use the regular `serve()` handler for this request, as\n // it's async.\n if (await this.isInngestReq(reqInit.actions)) {\n // If we have a run ID, we can just use the normal serve path\n // return this.createHandler()(...args);\n return this.handleAsyncRequest({\n ...reqInit,\n forceExecution: true,\n args,\n fns: [fn],\n });\n }\n\n // Otherwise, we know this is a sync request, so we can proceed with\n // creating a sync request to Inngest.\n return this.handleSyncRequest({\n ...reqInit,\n args,\n asyncMode:\n this._options.syncOptions?.asyncResponse ??\n AsyncResponseType.Redirect,\n asyncRedirectUrl: this._options.syncOptions?.asyncRedirectUrl,\n fn,\n });\n }) as THandler);\n };\n }\n\n /**\n * `createHandler` should be used to return a type-equivalent version of the\n * `handler` specified during instantiation.\n *\n * @example\n * ```\n * // my-custom-handler.ts\n * import {\n * InngestCommHandler,\n * type ServeHandlerOptions,\n * } from \"./components/InngestCommHandler\";\n *\n * export const serve = (options: ServeHandlerOptions) => {\n * const handler = new InngestCommHandler({\n * frameworkName: \"my-custom-handler\",\n * ...options,\n * handler: (req: Request) => {\n * return {\n * body: () => req.json(),\n * headers: (key) => req.headers.get(key),\n * method: () => req.method,\n * url: () => new URL(req.url, `https://${req.headers.get(\"host\") || \"\"}`),\n * transformResponse: ({ body, status, headers }) => {\n * return new Response(body, { status, headers });\n * },\n * };\n * },\n * });\n *\n * return handler.createHandler();\n * };\n * ```\n */\n public createHandler<\n THandler extends (...args: Input) => Promise<Awaited<Output>>,\n >(): THandler {\n return this.wrapHandler((async (...args) => {\n return this.handleAsyncRequest({\n ...(await this.initRequest(...args)),\n args,\n });\n }) as THandler);\n }\n\n /**\n * Given a set of actions that let us access the incoming request, create an\n * event that repesents a run starting from an HTTP request.\n */\n private async createHttpEvent(\n actions: HandlerResponseWithErrors,\n fn: InngestFunction.Any,\n ): Promise<APIStepPayload> {\n const reason = \"creating sync event\";\n\n const contentTypePromise = actions\n .headers(reason, headerKeys.ContentType)\n .then((v) => v ?? \"\");\n\n const ipPromise = actions\n .headers(reason, headerKeys.ForwardedFor)\n .then((v) => {\n if (v) return v;\n\n return actions.headers(reason, headerKeys.RealIp).then((v) => v ?? \"\");\n });\n\n const methodPromise = actions.method(reason);\n\n const urlPromise = actions.url(reason).then((v) => this.reqUrl(v));\n\n const domainPromise = urlPromise.then(\n (url) => `${url.protocol}//${url.host}`,\n );\n\n const pathPromise = urlPromise.then((url) => url.pathname);\n\n const queryParamsPromise = urlPromise.then((url) =>\n url.searchParams.toString(),\n );\n\n const bodyPromise = actions.body(reason).then((body) => {\n return typeof body === \"string\" ? body : stringify(body);\n });\n\n const [contentType, domain, ip, method, path, queryParams, body] =\n await Promise.all([\n contentTypePromise,\n domainPromise,\n ipPromise,\n methodPromise,\n pathPromise,\n queryParamsPromise,\n bodyPromise,\n ]);\n\n return {\n name: internalEvents.HttpRequest,\n data: {\n content_type: contentType,\n domain,\n ip,\n method,\n path,\n query_params: queryParams,\n body,\n fn: fn.id(),\n },\n };\n }\n\n private async handleSyncRequest({\n timer,\n actions,\n fn,\n asyncMode,\n asyncRedirectUrl,\n args,\n }: {\n timer: ServerTiming;\n actions: HandlerResponseWithErrors;\n fn: InngestFunction.Any;\n asyncMode: AsyncResponseValue;\n asyncRedirectUrl: SyncHandlerOptions[\"asyncRedirectUrl\"];\n args: unknown[];\n }): Promise<Awaited<Output>> {\n // Do we have actions for handling sync requests? We must!\n if (!actions.experimentalTransformSyncResponse) {\n throw new Error(\n \"This platform does not support synchronous Inngest function executions.\",\n );\n }\n\n // Check we're not in a context already...\n const ctx = await getAsyncCtx();\n if (ctx) {\n throw new Error(\n \"We already seem to be in the context of an Inngest execution, but didn't expect to be. Did you already wrap this handler?\",\n );\n }\n\n // We create a new run ID here in the SDK.\n const { ulid } = await import(\"ulid\"); // lazy loading for edge envs\n const runId = ulid();\n const event = await this.createHttpEvent(actions, fn);\n\n const acceptHeader = await actions.headers(\n \"checking accept header\",\n \"Accept\",\n );\n const acceptsSse = acceptHeader?.includes(\"text/event-stream\") ?? false;\n\n const exeVersion = ExecutionVersion.V2;\n\n const exe = fn[\"createExecution\"]({\n partialOptions: {\n client: this.client,\n data: {\n runId,\n event,\n attempt: 0,\n events: [event],\n maxAttempts: fn.opts.retries ?? defaultMaxRetries,\n },\n runId,\n headers: {},\n reqArgs: args,\n stepCompletionOrder: [],\n stepState: {},\n disableImmediateExecution: false,\n isFailureHandler: false,\n acceptsSse,\n timer,\n createResponse: (data: unknown) =>\n actions.experimentalTransformSyncResponse!(\n \"creating sync execution\",\n data,\n ).then((res) => ({\n ...res,\n version: exeVersion,\n })),\n stepMode: StepMode.Sync,\n },\n });\n\n const result = await exe.start();\n\n const resultHandlers: ExecutionResultHandlers<unknown> = {\n \"step-not-found\": () => {\n throw new Error(\n \"We should not get the result 'step-not-found' when checkpointing. This is a bug in the `inngest` SDK\",\n );\n },\n \"steps-found\": () => {\n throw new Error(\n \"We should not get the result 'steps-found' when checkpointing. This is a bug in the `inngest` SDK\",\n );\n },\n \"step-ran\": () => {\n throw new Error(\n \"We should not get the result 'step-ran' when checkpointing. This is a bug in the `inngest` SDK\",\n );\n },\n \"function-rejected\": (result) => {\n return actions.transformResponse(\"creating sync error response\", {\n status: result.retriable ? 500 : 400,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: result.retriable ? \"false\" : \"true\",\n ...(typeof result.retriable === \"string\"\n ? { [headerKeys.RetryAfter]: result.retriable }\n : {}),\n },\n version: exeVersion,\n body: stringify(undefinedToNull(result.error)),\n });\n },\n \"function-resolved\": ({ data }) => {\n // If the execution returned a Response (SSE streaming from the\n // engine, or a user-constructed Response in a durable endpoint),\n // pass it through directly — the headers and body are already set.\n if (data instanceof Response) {\n return data;\n }\n\n // Non-streaming path: plain return values from the function are\n // JSON-serialized and wrapped in a framework response.\n return actions.transformResponse(\"creating sync success response\", {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: exeVersion,\n body: stringify(undefinedToNull(data)),\n });\n },\n \"change-mode\": async ({ token }) => {\n switch (asyncMode) {\n case AsyncResponseType.Redirect: {\n let redirectUrl: string;\n\n if (asyncRedirectUrl) {\n if (typeof asyncRedirectUrl === \"function\") {\n // Full control: user provides complete URL\n redirectUrl = await asyncRedirectUrl({ runId, token });\n } else {\n // String path: resolve relative to request origin\n // new URL(\"/api/poll\", \"https://example.com\") → \"https://example.com/api/poll\"\n // new URL(\"https://other.com/poll\", \"https://example.com\") → \"https://other.com/poll\"\n const baseUrl = await actions.url(\"getting request origin\");\n const url = new URL(asyncRedirectUrl, baseUrl.origin);\n url.searchParams.set(\"runId\", runId);\n url.searchParams.set(\"token\", token);\n redirectUrl = url.toString();\n }\n } else {\n // Default: redirect to Inngest API\n redirectUrl = await this.client[\"inngestApi\"]\n [\"getTargetUrl\"](`/v1/http/runs/${runId}/output?token=${token}`)\n .then((url) => url.toString());\n }\n\n return actions.transformResponse(\n \"creating sync->async redirect response\",\n {\n status: 302,\n headers: {\n [headerKeys.Location]: redirectUrl,\n },\n version: exeVersion,\n body: \"\",\n },\n );\n }\n\n case AsyncResponseType.Token: {\n return actions.transformResponse(\n \"creating sync->async token response\",\n {\n status: 200,\n headers: {},\n version: exeVersion,\n body: stringify({ run_id: runId, token }),\n },\n );\n }\n\n default: {\n // TODO user-provided hook mate, incl. req args\n break;\n }\n }\n\n throw new Error(\"Not implemented: change-mode\");\n },\n };\n\n const resultHandler = resultHandlers[\n result.type\n ] as ExecutionResultHandler<unknown>;\n if (!resultHandler) {\n throw new Error(\n `No handler for execution result type: ${result.type}. This is a bug in the \\`inngest\\` SDK`,\n );\n }\n\n return resultHandler(result) as Awaited<Output>;\n }\n\n private async handleAsyncRequest({\n timer,\n actions,\n args,\n getHeaders,\n forceExecution,\n fns,\n }: {\n timer: ServerTiming;\n actions: HandlerResponseWithErrors;\n args: Input;\n getHeaders: () => Promise<Record<string, string>>;\n forceExecution?: boolean;\n fns?: InngestFunction.Any[];\n }): Promise<Awaited<Output>> {\n if (forceExecution && !actions.experimentalTransformSyncResponse) {\n throw new Error(\n \"This platform does not support async executions in Inngest for APIs.\",\n );\n }\n\n const methodP = actions.method(\"starting to handle request\");\n\n const [signature, method, body] = await Promise.all([\n actions\n .headers(\"checking signature for request\", headerKeys.Signature)\n .then((headerSignature) => {\n return headerSignature ?? undefined;\n }),\n methodP,\n methodP.then(async (method) => {\n if (method === \"POST\" || method === \"PUT\") {\n const body = await actions.body(\n `checking body for request signing as method is ${method}`,\n );\n if (!body) {\n // Empty body can happen with PUT requests\n return \"\";\n }\n // Some adapters return strings (req.text()), others return\n // pre-parsed objects (req.body). Handle both cases.\n if (typeof body === \"string\") {\n return JSON.parse(body);\n }\n return body;\n }\n\n return \"\";\n }),\n ]);\n\n const signatureValidation = this.validateSignature(signature, body);\n\n // Create middleware instances once; shared by wrapRequest and execution hooks.\n // Starts with client-level middleware; function-level middleware is appended\n // for POST requests once the target function is known.\n const mwInstances = this.client.middleware.map(\n (Cls) => new Cls({ client: this.client }),\n );\n\n /**\n * Prepares an action response by merging returned data to provide\n * trailing information such as `Server-Timing` headers.\n *\n * It should always prioritize the headers returned by the action, as they\n * may contain important information such as `Content-Type`.\n */\n const prepareActionRes = async (\n res: ActionResponse,\n ): Promise<ActionResponse> => {\n const headers: Record<string, string> = {\n ...(await getHeaders()),\n ...res.headers,\n ...(res.version === null\n ? {}\n : {\n [headerKeys.RequestVersion]: (\n res.version ?? PREFERRED_ASYNC_EXECUTION_VERSION\n ).toString(),\n }),\n };\n\n let signature: string | undefined;\n\n try {\n signature = await signatureValidation.then(async (result) => {\n if (!result.success || !result.keyUsed) {\n return undefined;\n }\n\n return await this.getResponseSignature(result.keyUsed, res.body);\n });\n } catch (err) {\n // If we fail to sign, retun a 500 with the error.\n return {\n ...res,\n headers,\n body: stringify(serializeError(err)),\n status: 500,\n };\n }\n\n if (signature) {\n headers[headerKeys.Signature] = signature;\n }\n\n return {\n ...res,\n headers,\n };\n };\n\n // Build the inner handler that wraps handleAction + prepareActionRes.\n // We capture `version` via closure so it can be passed to transformResponse.\n let actionResponseVersion: ExecutionVersion | null | undefined;\n\n const handleAndPrepare = async (): Promise<ActionResponse> => {\n const rawRes = await timer.wrap(\"action\", () =>\n this.handleAction({\n actions,\n timer,\n getHeaders,\n reqArgs: args,\n signatureValidation,\n body,\n method,\n forceExecution: Boolean(forceExecution),\n fns,\n mwInstances,\n }),\n );\n actionResponseVersion = rawRes.version;\n const prepared = await prepareActionRes(rawRes);\n\n // Unauthenticated responses must not leak SDK identification headers,\n // so we strip every `x-inngest-*` header except `x-inngest-sdk-handled`\n // (which the Inngest backend uses to know that the SDK produced the\n // response, useful for troubleshooting). `User-Agent` is also stripped\n // since it advertises the SDK and version. In dev mode, signature\n // validation short-circuits to success so this branch is a no-op.\n const validation = await signatureValidation;\n if (!validation.success) {\n const filteredHeaders: Record<string, string> = {};\n for (const [k, v] of Object.entries(prepared.headers)) {\n const lower = k.toLowerCase();\n if (lower === \"user-agent\") {\n // User-Agent contains the SDK version\n continue;\n }\n if (\n lower.startsWith(\"x-inngest-\") &&\n lower !== headerKeys.SdkHandled.toLowerCase()\n ) {\n continue;\n }\n filteredHeaders[k] = v;\n }\n\n return { ...prepared, headers: filteredHeaders };\n }\n\n return prepared;\n };\n\n // Only wrap POST requests with the wrapRequest middleware chain.\n // GET/PUT (introspection, registration) bypass the middleware.\n let chainResult: Promise<Middleware.Response>;\n if (method === \"POST\") {\n const url = await actions.url(\"building requestInfo for middleware\");\n\n // Append function-level middleware so it is scoped to this function only.\n const fnId = url.searchParams.get(queryKeys.FnId);\n const matchedFn = fnId ? this.fns[fnId] : undefined;\n const fnMw = matchedFn?.fn?.opts?.middleware ?? [];\n mwInstances.push(\n ...fnMw.map((Cls) => {\n return new Cls({ client: this.client });\n }),\n );\n\n const fn = matchedFn?.fn ?? null;\n\n const requestInfo: Middleware.Request = {\n headers: Object.freeze({ ...(await getHeaders()) }),\n method,\n url,\n body: () => Promise.resolve(body),\n };\n\n let runId = \"\";\n if (\n isRecord(body) &&\n isRecord(body.ctx) &&\n body.ctx.run_id &&\n typeof body.ctx.run_id === \"string\"\n ) {\n runId = body.ctx.run_id;\n }\n\n const innerHandler = async (): Promise<Middleware.Response> => {\n const prepared = await handleAndPrepare();\n return {\n status: prepared.status,\n headers: prepared.headers,\n body: prepared.body,\n };\n };\n\n const wrappedHandler = buildWrapRequestChain({\n fn,\n handler: innerHandler,\n middleware: mwInstances,\n requestArgs: args,\n requestInfo,\n runId,\n });\n\n // Start eagerly (matches prior behavior where handleAction starts before\n // the shouldStream check).\n chainResult = wrappedHandler();\n } else {\n chainResult = handleAndPrepare().then((prepared) => ({\n status: prepared.status,\n headers: prepared.headers,\n body: prepared.body,\n }));\n }\n\n // Attach error handling: if wrapRequest middleware throws, convert to 500.\n const safeChainResult = chainResult.catch(\n (err): Middleware.Response => ({\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n body: stringify({\n type: \"internal\",\n ...serializeError(err as Error),\n }),\n }),\n );\n\n let shouldStream: boolean;\n try {\n shouldStream = await this.shouldStream(actions);\n } catch (err) {\n return actions.transformResponse(\"sending back response\", {\n status: 500,\n headers: {\n ...(await getHeaders()),\n \"Content-Type\": \"application/json\",\n },\n body: stringify(serializeError(err)),\n version: undefined,\n });\n }\n\n if (shouldStream) {\n const method = await actions.method(\"starting streaming response\");\n\n if (method === \"POST\") {\n const { stream, finalize } = await createStream();\n\n /**\n * Errors are handled by `handleAction` here to ensure that an\n * appropriate response is always given.\n */\n void safeChainResult.then((res) => {\n return finalize(\n Promise.resolve({\n ...res,\n version: actionResponseVersion,\n }),\n );\n });\n\n return timer.wrap(\"res\", async () => {\n return actions.transformStreamingResponse?.(\n \"starting streaming response\",\n {\n status: 201,\n headers: await getHeaders(),\n body: stream,\n version: null,\n },\n );\n });\n }\n }\n\n return timer.wrap(\"res\", async () => {\n return safeChainResult.then((res) => {\n return actions.transformResponse(\"sending back response\", {\n ...res,\n version: actionResponseVersion,\n });\n });\n });\n }\n\n private async getActions(\n timer: ServerTiming,\n ...args: Input\n ): Promise<HandlerResponseWithErrors> {\n /**\n * Used for testing, allow setting action overrides externally when\n * calling the handler. Always search the final argument.\n */\n const lastArg = args[args.length - 1] as unknown;\n const actionOverrides =\n typeof lastArg === \"object\" &&\n lastArg !== null &&\n \"actionOverrides\" in lastArg &&\n typeof lastArg[\"actionOverrides\"] === \"object\" &&\n lastArg[\"actionOverrides\"] !== null\n ? lastArg[\"actionOverrides\"]\n : {};\n\n /**\n * We purposefully `await` the handler, as it could be either sync or\n * async.\n */\n const rawActions = {\n ...(await timer\n .wrap(\"handler\", () => this.handler(...args))\n .catch(rethrowError(\"Serve handler failed to run\"))),\n ...actionOverrides,\n };\n\n /**\n * Map over every `action` in `rawActions` and create a new `actions`\n * object where each function is safely promisified with each access\n * requiring a reason.\n *\n * This helps us provide high quality errors about what's going wrong for\n * each access without having to wrap every access in a try/catch.\n */\n const promisifiedActions: ActionHandlerResponseWithErrors = Object.entries(\n rawActions,\n ).reduce((acc, [key, value]) => {\n if (typeof value !== \"function\") {\n return acc;\n }\n\n return {\n ...acc,\n [key]: (reason: string, ...args: unknown[]) => {\n const errMessage = [\n `Failed calling \\`${key}\\` from serve handler`,\n reason,\n ]\n .filter(Boolean)\n .join(\" when \");\n\n const fn = () => (value as (...args: unknown[]) => unknown)(...args);\n\n return runAsPromise(fn)\n .catch(rethrowError(errMessage))\n .catch((err) => {\n this.client[internalLoggerSymbol].error({ err }, errMessage);\n throw err;\n });\n },\n };\n }, {} as ActionHandlerResponseWithErrors);\n\n /**\n * Mapped promisified handlers from userland `serve()` function mixed in\n * with some helpers.\n */\n const actions: HandlerResponseWithErrors = {\n ...promisifiedActions,\n queryStringWithDefaults: async (\n reason: string,\n key: string,\n ): Promise<string | undefined> => {\n const url = await actions.url(reason);\n\n const ret =\n (await actions.queryString?.(reason, key, url)) ||\n url.searchParams.get(key) ||\n undefined;\n\n return ret;\n },\n ...actionOverrides,\n };\n\n return actions;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: any fn\n private wrapHandler<THandler extends (...args: any[]) => any>(\n handler: THandler,\n ): THandler {\n /**\n * Some platforms check (at runtime) the length of the function being used\n * to handle an endpoint. If this is a variadic function, it will fail that\n * check.\n *\n * Therefore, we expect the arguments accepted to be the same length as the\n * `handler` function passed internally.\n *\n * We also set a name to avoid a common useless name in tracing such as\n * `\"anonymous\"` or `\"bound function\"`.\n *\n * https://github.com/getsentry/sentry-javascript/issues/3284\n */\n Object.defineProperties(handler, {\n name: {\n value: \"InngestHandler\",\n },\n length: {\n value: this.handler.length,\n },\n });\n\n return handler;\n }\n\n /**\n * Given a set of functions to check if an action is available from the\n * instance's handler, enact any action that is found.\n *\n * This method can fetch varying payloads of data, but ultimately is the place\n * where _decisions_ are made regarding functionality.\n *\n * For example, if we find that we should be viewing the UI, this function\n * will decide whether the UI should be visible based on the payload it has\n * found (e.g. env vars, options, etc).\n */\n private async handleAction({\n actions,\n timer,\n getHeaders,\n reqArgs,\n signatureValidation,\n body: rawBody,\n method,\n forceExecution,\n fns,\n mwInstances,\n }: {\n actions: HandlerResponseWithErrors;\n timer: ServerTiming;\n getHeaders: () => Promise<Record<string, string>>;\n reqArgs: unknown[];\n signatureValidation: ReturnType<InngestCommHandler[\"validateSignature\"]>;\n body: unknown;\n method: string;\n forceExecution: boolean;\n fns?: InngestFunction.Any[];\n mwInstances?: Middleware.BaseMiddleware[];\n }): Promise<ActionResponse> {\n if (!this.checkModeConfiguration()) {\n return internalServerErrorResponse;\n }\n\n // This is when the request body is completely missing. This commonly\n // happens when the HTTP framework doesn't have body parsing middleware,\n // or for PUT requests that don't require a body.\n const isMissingBody = !rawBody;\n let body = rawBody;\n\n try {\n let url = await actions.url(\"starting to handle request\");\n\n if (method === \"POST\" || forceExecution) {\n if (!forceExecution && isMissingBody) {\n this.client[internalLoggerSymbol].error(\n \"Missing body when executing, possibly due to missing request body middleware\",\n );\n\n return {\n status: 401,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify({ message: \"Unauthorized\" }),\n version: undefined,\n };\n }\n\n const validationResult = await signatureValidation;\n if (!validationResult.success) {\n this.client[internalLoggerSymbol].error(\n { err: validationResult.err },\n \"Signature validation failed\",\n );\n\n return {\n status: 401,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify({ message: \"Unauthorized\" }),\n version: undefined,\n };\n }\n\n let fn: { fn: InngestFunction.Any; onFailure: boolean } | undefined;\n let fnId: string | undefined;\n\n if (forceExecution) {\n fn =\n fns?.length && fns[0]\n ? { fn: fns[0], onFailure: false }\n : Object.values(this.fns)[0];\n fnId = fn?.fn.id();\n\n // Grab \"force step plan\" flag from headers\n let die = false;\n const dieHeader = await actions.headers(\n \"getting step plan force control for forced execution\",\n headerKeys.InngestForceStepPlan,\n );\n if (dieHeader) {\n const parsed = parseAsBoolean(dieHeader);\n if (typeof parsed === \"boolean\") {\n die = parsed;\n } else {\n this.client[internalLoggerSymbol].warn(\n { header: headerKeys.InngestForceStepPlan, value: dieHeader },\n \"Invalid boolean header value; defaulting to false\",\n );\n }\n }\n\n body = {\n event: {},\n events: [],\n steps: {},\n version: PREFERRED_ASYNC_EXECUTION_VERSION,\n sdkDecided: true,\n ctx: {\n attempt: 0,\n disable_immediate_execution: die,\n use_api: true,\n // This execution path doesn't control max attempts; it's already\n // been reported and Inngest is now in control of when to stop, so\n // we remove this restriction.\n max_attempts: Infinity,\n run_id: await actions.headers(\n \"getting run ID for forced execution\",\n headerKeys.InngestRunId,\n ),\n // TODO We need this to be given to us or the API to return it\n stack: { stack: [], current: 0 },\n },\n } as Extract<\n FnData,\n { version: typeof PREFERRED_ASYNC_EXECUTION_VERSION }\n >;\n } else {\n const rawProbe = await actions.queryStringWithDefaults(\n \"testing for probe\",\n queryKeys.Probe,\n );\n if (rawProbe) {\n const probe = enumFromValue(probeEnum, rawProbe);\n if (!probe) {\n // If we're here, we've received a probe that we don't recognize.\n // Fail.\n return {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(\n serializeError(new Error(`Unknown probe \"${rawProbe}\"`)),\n ),\n version: undefined,\n };\n }\n\n // Provide actions for every probe available.\n const probeActions: Record<\n probeEnum,\n () => MaybePromise<ActionResponse>\n > = {\n [probeEnum.Trust]: () => ({\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: \"\",\n version: undefined,\n }),\n };\n\n return probeActions[probe]();\n }\n\n fnId = await actions.queryStringWithDefaults(\n \"processing run request\",\n queryKeys.FnId,\n );\n if (!fnId) {\n throw new Error(\"No function ID found in async request\");\n }\n\n fn = this.fns[fnId];\n }\n\n if (typeof fnId === \"undefined\" || !fn) {\n throw new Error(\"No function ID found in request\");\n }\n\n // Always try and grab the step ID; in regular async flows this will be\n // in the querystring, and in sync modes it'll be in the headers.\n const stepId =\n (await actions.queryStringWithDefaults(\n \"processing run request\",\n queryKeys.StepId,\n )) ||\n (await actions.headers(\n \"processing run request\",\n headerKeys.InngestStepId,\n )) ||\n null;\n\n // Try get the request version from headers for sync executions.\n let headerReqVersion: ExecutionVersion | undefined;\n\n try {\n const rawVersionHeader = await actions.headers(\n \"processing run request\",\n headerKeys.RequestVersion,\n );\n\n // We only obey the request version header if it's actually a number,\n // even though the underlying schema allows more values; that schema\n // is intended to _always_ find a valid version and made for request\n // bodies.\n //\n // Note that the header will be a `string` at this point.\n if (rawVersionHeader && Number.isFinite(Number(rawVersionHeader))) {\n const res = createVersionSchema(\n this.client[internalLoggerSymbol],\n ).parse(Number(rawVersionHeader));\n\n if (!res.sdkDecided) {\n headerReqVersion = res.version;\n }\n }\n } catch {\n // no-op\n }\n\n const resolvedHeaders = await getHeaders();\n const { version, result } = this.runStep({\n functionId: fnId,\n data: body,\n stepId,\n timer,\n reqArgs,\n headers: resolvedHeaders,\n fn,\n forceExecution,\n actions,\n headerReqVersion,\n requestInfo: {\n headers: Object.freeze({ ...resolvedHeaders }),\n method,\n url,\n body: () => Promise.resolve(body),\n },\n mwInstances,\n });\n const stepOutput = await result;\n\n /**\n * Functions can return `undefined`, but we'll always convert this to\n * `null`, as this is appropriately serializable by JSON.\n */\n const opDataUndefinedToNull = (op: OutgoingOp) => {\n op.data = undefinedToNull(op.data);\n return op;\n };\n\n const resultHandlers: ExecutionResultHandlers<ActionResponse> = {\n \"function-rejected\": (result) => {\n return {\n status: result.retriable ? 500 : 400,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: result.retriable ? \"false\" : \"true\",\n ...(typeof result.retriable === \"string\"\n ? { [headerKeys.RetryAfter]: result.retriable }\n : {}),\n },\n body: stringify(undefinedToNull(result.error)),\n version,\n };\n },\n \"function-resolved\": (result) => {\n if (forceExecution) {\n const runCompleteOp: OutgoingOp = {\n id: _internals.hashId(\"complete\"),\n op: StepOpCode.RunComplete,\n data: undefinedToNull(result.data),\n };\n\n return {\n status: 206,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(runCompleteOp),\n version,\n };\n }\n\n return {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(undefinedToNull(result.data)),\n version,\n };\n },\n \"step-not-found\": (result) => {\n // we want to show the names and IDs of any steps that were found during the\n // run process\n const missingStepId = result.step.displayName || result.step.id;\n\n let error = `Could not find step \"${missingStepId}\" to run; timed out.`;\n\n if (result.foundSteps.length > 0) {\n const foundStepsSummary = result.foundSteps\n .map((step) => {\n const name = step.displayName || step.id;\n return `${name} (${step.id})`;\n })\n .join(\"\\n\");\n error = `${error} Found new steps: \\n${foundStepsSummary}.`;\n }\n\n if (result.totalFoundSteps > result.foundSteps.length) {\n error = `${error} (showing ${result.foundSteps.length} of ${result.totalFoundSteps})`;\n }\n\n return {\n status: 500,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: \"false\",\n },\n body: stringify({\n error,\n requestedStep: result.step.id,\n foundSteps: result.foundSteps,\n totalFoundSteps: result.totalFoundSteps,\n }),\n version,\n };\n },\n \"step-ran\": (result) => {\n const step = opDataUndefinedToNull(result.step);\n\n return {\n status: 206,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(typeof result.retriable !== \"undefined\"\n ? {\n [headerKeys.NoRetry]: result.retriable ? \"false\" : \"true\",\n ...(typeof result.retriable === \"string\"\n ? { [headerKeys.RetryAfter]: result.retriable }\n : {}),\n }\n : {}),\n },\n body: stringify([step]),\n version,\n };\n },\n \"steps-found\": (result) => {\n const steps = result.steps.map(opDataUndefinedToNull);\n\n return {\n status: 206,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(steps),\n version,\n };\n },\n \"change-mode\": (result) => {\n return {\n status: 500,\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.NoRetry]: \"true\",\n },\n body: stringify({\n error: `We wanted to change mode to \"${result.to}\", but this is not supported within the InngestCommHandler. This is a bug in the Inngest SDK.`,\n }),\n version,\n };\n },\n };\n\n const handler = resultHandlers[\n stepOutput.type\n ] as ExecutionResultHandler<ActionResponse>;\n\n try {\n return await handler(stepOutput);\n } catch (err) {\n this.client[internalLoggerSymbol].error(\n { err },\n \"Error handling execution result\",\n );\n throw err;\n }\n }\n\n // TODO: This feels hacky, so we should probably make it not hacky.\n const env = (await getHeaders())[headerKeys.Environment] ?? null;\n\n if (method === \"GET\") {\n // In cloud mode, introspection requires a valid signature. We don't\n // serve an unauthenticated introspection body to anonymous callers\n // because it leaks deployment fingerprint (mode, function count,\n // event/signing key presence).\n if (this.client.mode === \"cloud\") {\n const validationResult = await signatureValidation;\n if (!validationResult.success) {\n this.client[internalLoggerSymbol].error(\n { err: validationResult.err },\n \"Signature validation failed\",\n );\n\n return {\n status: 401,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify({ message: \"Unauthorized\" }),\n version: undefined,\n };\n }\n }\n\n return {\n status: 200,\n body: stringify(\n await this.introspectionBody({\n actions,\n env,\n signatureValidation,\n url,\n }),\n ),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n if (method === \"PUT\") {\n const [deployId, inBandSyncRequested] = await Promise.all([\n actions\n .queryStringWithDefaults(\n \"processing deployment request\",\n queryKeys.DeployId,\n )\n .then((deployId) => {\n return deployId === \"undefined\" ? undefined : deployId;\n }),\n\n Promise.resolve(\n parseAsBoolean(this.env[envKeys.InngestAllowInBandSync]),\n )\n .then((allowInBandSync) => {\n if (allowInBandSync !== undefined && !allowInBandSync) {\n return syncKind.OutOfBand;\n }\n\n return actions.headers(\n \"processing deployment request\",\n headerKeys.InngestSyncKind,\n );\n })\n .then((kind) => {\n return kind === syncKind.InBand;\n }),\n ]);\n\n if (inBandSyncRequested) {\n if (isMissingBody) {\n this.client[internalLoggerSymbol].error(\n \"Missing body when syncing, possibly due to missing request body middleware\",\n );\n\n return {\n status: 500,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: stringify(\n serializeError(\n new Error(\n \"Missing request body when syncing, possibly due to missing request body middleware\",\n ),\n ),\n ),\n version: undefined,\n };\n }\n\n // Validation can be successful if we're in dev mode and did not\n // actually validate a key. In this case, also check that we did indeed\n // use a particular key to validate.\n const sigCheck = await signatureValidation;\n\n if (!sigCheck.success) {\n return {\n status: 401,\n body: stringify({\n code: \"sig_verification_failed\",\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n const res = inBandSyncRequestBodySchema.safeParse(body);\n if (!res.success) {\n return {\n status: 400,\n body: stringify({\n code: \"invalid_request\",\n message: res.error.message,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n // We can trust the URL here because it's coming from\n // signature-verified request.\n url = this.reqUrl(new URL(res.data.url));\n\n // This should be an in-band sync\n const respBody = await this.inBandRegisterBody({\n actions,\n deployId,\n env,\n signatureValidation,\n url,\n });\n\n return {\n status: 200,\n body: stringify(respBody),\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.InngestSyncKind]: syncKind.InBand,\n },\n version: undefined,\n };\n }\n\n // If we're here, this is a legacy out-of-band sync\n const { status, message, modified } = await this.register(\n this.reqUrl(url),\n deployId,\n getHeaders,\n );\n\n return {\n status,\n body: stringify({ message, modified }),\n headers: {\n \"Content-Type\": \"application/json\",\n [headerKeys.InngestSyncKind]: syncKind.OutOfBand,\n },\n version: undefined,\n };\n }\n } catch (err) {\n return {\n status: 500,\n body: stringify({\n type: \"internal\",\n ...serializeError(err as Error),\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n this.client[internalLoggerSymbol].error(\n { method },\n \"Received unhandled HTTP method; expected POST, PUT, or GET\",\n );\n\n return {\n status: 405,\n body: JSON.stringify({ message: \"Method not allowed\" }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n version: undefined,\n };\n }\n\n protected runStep({\n actions,\n functionId,\n stepId,\n data,\n timer,\n reqArgs,\n headers,\n fn,\n forceExecution,\n headerReqVersion,\n requestInfo,\n mwInstances,\n }: {\n actions: HandlerResponseWithErrors;\n functionId: string;\n stepId: string | null;\n data: unknown;\n timer: ServerTiming;\n reqArgs: unknown[];\n headers: Record<string, string>;\n fn: { fn: InngestFunction.Any; onFailure: boolean };\n forceExecution: boolean;\n headerReqVersion?: ExecutionVersion;\n requestInfo?: InngestExecutionOptions[\"requestInfo\"];\n mwInstances?: Middleware.BaseMiddleware[];\n }): { version: ExecutionVersion; result: Promise<ExecutionResult> } {\n if (!fn) {\n throw new Error(`Could not find function with ID \"${functionId}\"`);\n }\n\n // Try to get the request version from headers before falling back to\n // parsing it from the body.\n const immediateFnData = parseFnData(\n data,\n headerReqVersion,\n this.client[internalLoggerSymbol],\n );\n const { sdkDecided } = immediateFnData;\n let version = ExecutionVersion.V2;\n\n // Handle opting out of optimized parallelism\n if (\n version === ExecutionVersion.V2 &&\n sdkDecided &&\n fn.fn[\"shouldOptimizeParallelism\"]?.() === false\n ) {\n version = ExecutionVersion.V1;\n }\n\n const result = runAsPromise(async () => {\n const anyFnData = await fetchAllFnData({\n data: immediateFnData,\n api: this.client[\"inngestApi\"],\n logger: this.client[internalLoggerSymbol],\n });\n\n if (!anyFnData.ok) {\n throw new Error(anyFnData.error);\n }\n\n const createResponse =\n forceExecution && actions.experimentalTransformSyncResponse\n ? (data: unknown) =>\n actions.experimentalTransformSyncResponse!(\n \"created sync->async response\",\n data,\n ).then((res) => ({\n ...res,\n version,\n }))\n : undefined;\n\n const { event, events, steps, ctx } = anyFnData.value;\n\n const stepState = Object.entries(steps ?? {}).reduce<\n InngestExecutionOptions[\"stepState\"]\n >((acc, [id, result]) => {\n return {\n ...acc,\n [id]:\n result.type === \"data\"\n ? { id, data: result.data }\n : result.type === \"input\"\n ? { id, input: result.input }\n : { id, error: result.error },\n };\n }, {});\n\n const requestedRunStep =\n stepId === \"step\" ? undefined : stepId || undefined;\n\n const checkpointingConfig = fn.fn[\"shouldAsyncCheckpoint\"](\n requestedRunStep,\n ctx?.fn_id,\n Boolean(ctx?.disable_immediate_execution),\n this.defaultMaxRuntime,\n );\n\n const executionOptions: CreateExecutionOptions = {\n partialOptions: {\n client: this.client,\n runId: ctx?.run_id || \"\",\n stepMode: checkpointingConfig\n ? StepMode.AsyncCheckpointing\n : StepMode.Async,\n checkpointingConfig,\n data: {\n event: event as EventPayload,\n events: events as [EventPayload, ...EventPayload[]],\n runId: ctx?.run_id || \"\",\n attempt: ctx?.attempt ?? 0,\n maxAttempts: ctx?.max_attempts,\n },\n internalFnId: ctx?.fn_id,\n queueItemId: ctx?.qi_id,\n stepState,\n requestedRunStep,\n timer,\n isFailureHandler: fn.onFailure,\n disableImmediateExecution: ctx?.disable_immediate_execution,\n stepCompletionOrder: ctx?.stack?.stack ?? [],\n reqArgs,\n headers,\n createResponse,\n requestInfo,\n middlewareInstances: mwInstances,\n },\n };\n\n return fn.fn[\"createExecution\"](executionOptions).start();\n });\n\n return { version, result };\n }\n\n protected configs(url: URL): FunctionConfig[] {\n const configs = Object.values(this.rawFns).reduce<FunctionConfig[]>(\n (acc, fn) => [\n ...acc,\n ...fn[\"getConfig\"]({ baseUrl: url, appPrefix: this.client.id }),\n ],\n [],\n );\n\n for (const config of configs) {\n const check = functionConfigSchema.safeParse(config);\n if (!check.success) {\n const errors = check.error.errors.map((err) => err.message).join(\"; \");\n\n this.client[internalLoggerSymbol].warn(\n { functionId: config.id, errors },\n \"Invalid function config\",\n );\n }\n }\n\n return configs;\n }\n\n /**\n * Return an Inngest serve endpoint URL given a potential `path` and `host`.\n *\n * Will automatically use the `serveOrigin` and `servePath` if they have been\n * set when registering.\n */\n protected reqUrl(url: URL): URL {\n let ret = new URL(url);\n\n const servePath = this.servePath || this.env[envKeys.InngestServePath];\n\n if (servePath) {\n ret.pathname = servePath;\n }\n\n if (this.serveOrigin) {\n ret = new URL(ret.pathname + ret.search, this.serveOrigin);\n }\n\n return ret;\n }\n\n protected registerBody({\n url,\n deployId,\n }: {\n url: URL;\n\n /**\n * Non-optional to ensure we always consider if we have a deploy ID\n * available to us to use.\n */\n deployId: string | undefined | null;\n }): RegisterRequest {\n const body: RegisterRequest = {\n url: url.href,\n deployType: \"ping\",\n framework: this.frameworkName,\n appName: this.client.id,\n functions: this.configs(url),\n sdk: `js:v${version}`,\n v: \"0.1\",\n deployId: deployId || undefined,\n capabilities: {\n trust_probe: \"v1\",\n connect: \"v1\",\n },\n appVersion: this.client.appVersion,\n };\n\n return body;\n }\n\n protected async inBandRegisterBody({\n actions,\n deployId,\n env,\n signatureValidation,\n url,\n }: {\n actions: HandlerResponseWithErrors;\n\n /**\n * Non-optional to ensure we always consider if we have a deploy ID\n * available to us to use.\n */\n deployId: string | undefined | null;\n\n env: string | null;\n signatureValidation: ReturnType<InngestCommHandler[\"validateSignature\"]>;\n\n url: URL;\n }): Promise<InBandRegisterRequest> {\n const registerBody = this.registerBody({ deployId, url });\n const introspectionBody = await this.introspectionBody({\n actions,\n env,\n signatureValidation,\n url,\n });\n\n const body: InBandRegisterRequest = {\n app_id: this.client.id,\n appVersion: this.client.appVersion,\n capabilities: registerBody.capabilities,\n env,\n framework: registerBody.framework,\n functions: registerBody.functions,\n inspection: introspectionBody,\n platform: getPlatformName({\n ...getProcessEnv(),\n ...this.env,\n }),\n sdk_author: \"inngest\",\n sdk_language: \"\",\n sdk_version: \"\",\n sdk: registerBody.sdk,\n url: registerBody.url,\n };\n\n if (\n \"authentication_succeeded\" in introspectionBody &&\n introspectionBody.authentication_succeeded\n ) {\n body.sdk_language = introspectionBody.sdk_language;\n body.sdk_version = introspectionBody.sdk_version;\n }\n\n return body;\n }\n\n protected async introspectionBody({\n actions,\n env,\n signatureValidation,\n url,\n }: {\n actions: HandlerResponseWithErrors;\n env: string | null;\n signatureValidation: ReturnType<InngestCommHandler[\"validateSignature\"]>;\n url: URL;\n }): Promise<UnauthenticatedIntrospection | AuthenticatedIntrospection> {\n const registerBody = this.registerBody({\n url: this.reqUrl(url),\n deployId: null,\n });\n\n if (!this.client.mode) {\n throw new Error(\"No mode set; cannot introspect without mode\");\n }\n\n let introspection:\n | UnauthenticatedIntrospection\n | AuthenticatedIntrospection = {\n extra: {\n native_crypto: globalThis.crypto?.subtle ? true : false,\n },\n has_event_key: this.client[\"eventKeySet\"](),\n has_signing_key: Boolean(this.client.signingKey),\n function_count: registerBody.functions.length,\n mode: this.client.mode,\n schema_version: \"2024-05-24\",\n } satisfies UnauthenticatedIntrospection;\n\n // Only allow authenticated introspection in Cloud mode, since Dev mode skips\n // signature validation\n if (this.client.mode === \"cloud\") {\n try {\n const validationResult = await signatureValidation;\n if (!validationResult.success) {\n throw new Error(\"Signature validation failed\");\n }\n\n // For the signing keys, only send the first 12 characters of the hash.\n // It's technically safe to send the full hash since the request was\n // authenticated, but we'll play it safe and only send the first 12\n // characters. 12 characters is enough to uniquely identify the key\n // without revealing the full hash.\n let signingKeyHash: string | null = null;\n if (this.hashedSigningKey) {\n signingKeyHash = removeSigningKeyPrefix(this.hashedSigningKey).slice(\n 0,\n 12,\n );\n }\n let signingKeyFallbackHash: string | null = null;\n if (this.hashedSigningKeyFallback) {\n signingKeyFallbackHash = removeSigningKeyPrefix(\n this.hashedSigningKeyFallback,\n ).slice(0, 12);\n }\n\n introspection = {\n ...introspection,\n authentication_succeeded: true,\n api_origin: this.client.apiBaseUrl,\n app_id: this.client.id,\n capabilities: {\n trust_probe: \"v1\",\n connect: \"v1\",\n },\n env,\n event_api_origin: this.client.eventBaseUrl,\n event_key_hash: this.hashedEventKey ?? null,\n extra: {\n ...introspection.extra,\n is_streaming: await this.shouldStream(actions),\n native_crypto: globalThis.crypto?.subtle ? true : false,\n },\n framework: this.frameworkName,\n sdk_language: \"js\",\n sdk_version: version,\n serve_origin: this.serveOrigin ?? null,\n serve_path: this.servePath ?? null,\n signing_key_fallback_hash: signingKeyFallbackHash,\n signing_key_hash: signingKeyHash,\n } satisfies AuthenticatedIntrospection;\n } catch {\n // Swallow signature validation error since we'll just return the\n // unauthenticated introspection\n introspection = {\n ...introspection,\n } satisfies UnauthenticatedIntrospection;\n }\n }\n\n return introspection;\n }\n\n protected async register(\n url: URL,\n deployId: string | undefined | null,\n getHeaders: () => Promise<Record<string, string>>,\n ): Promise<{ status: number; message: string; modified: boolean }> {\n const body = this.registerBody({ url, deployId });\n\n let res: globalThis.Response;\n\n // Clone the URL object to avoid mutating the property between requests.\n const registerUrl = new URL(this.inngestRegisterUrl.href);\n\n if (deployId) {\n registerUrl.searchParams.set(queryKeys.DeployId, deployId);\n }\n\n try {\n res = await fetchWithAuthFallback({\n authToken: this.hashedSigningKey,\n authTokenFallback: this.hashedSigningKeyFallback,\n fetch: this.client.fetch,\n url: registerUrl.href,\n options: {\n method: \"POST\",\n body: stringify(body),\n headers: {\n ...(await getHeaders()),\n [headerKeys.InngestSyncKind]: syncKind.OutOfBand,\n },\n redirect: \"follow\",\n },\n });\n } catch (err: unknown) {\n this.client[internalLoggerSymbol].error({ err }, \"Failed to register\");\n\n return {\n status: 500,\n message: `Failed to register${\n err instanceof Error ? `; ${err.message}` : \"\"\n }`,\n modified: false,\n };\n }\n\n const raw = await res.text();\n\n let data: z.input<typeof registerResSchema> = {};\n\n try {\n data = JSON.parse(raw);\n } catch (err) {\n this.client[internalLoggerSymbol].warn(\n { err },\n \"Couldn't unpack register response\",\n );\n\n let message = \"Failed to register\";\n if (err instanceof Error) {\n message += `; ${err.message}`;\n }\n message += `; status code: ${res.status}`;\n\n return {\n status: 500,\n message,\n modified: false,\n };\n }\n\n let status: number;\n let error: string;\n let skipped: boolean;\n let modified: boolean;\n try {\n ({ status, error, skipped, modified } = registerResSchema.parse(data));\n } catch (err) {\n this.client[internalLoggerSymbol].warn(\n { err },\n \"Invalid register response schema\",\n );\n\n let message = \"Failed to register\";\n if (err instanceof Error) {\n message += `; ${err.message}`;\n }\n message += `; status code: ${res.status}`;\n\n return {\n status: 500,\n message,\n modified: false,\n };\n }\n\n // The dev server polls this endpoint to register functions every few\n // seconds, but we only want to log that we've registered functions if\n // the function definitions change. Therefore, we compare the body sent\n // during registration with the body of the current functions and refuse\n // to register if the functions are the same.\n if (!skipped) {\n this.client[internalLoggerSymbol].debug(\"Registered inngest functions\");\n }\n\n return { status, message: error, modified };\n }\n\n /**\n * Check that the current mode has the configuration it requires.\n * Returns `true` if valid, `false` if not.\n */\n checkModeConfiguration(): boolean {\n this.client.setEnvVars(this.env);\n\n return checkModeConfiguration({\n mode: this.client.mode,\n signingKey: this.client.signingKey,\n internalLogger: this.client[internalLoggerSymbol],\n });\n }\n\n /**\n * Validate the signature of a request and return the signing key used to\n * validate it.\n */\n\n protected async validateSignature(\n sig: string | undefined,\n body: unknown,\n ): Promise<\n { success: true; keyUsed: string } | { success: false; err: Error }\n > {\n try {\n // Skip signature validation if requested (used by connect)\n if (this.skipSignatureValidation) {\n return { success: true, keyUsed: \"\" };\n }\n\n // Never validate signatures outside of prod. Make sure to check the mode\n // exists here instead of using nullish coalescing to confirm that the check\n // has been completed.\n if (this.client.mode !== \"cloud\") {\n return { success: true, keyUsed: \"\" };\n }\n\n // If we're here, we're in production; lack of a signing key is an error.\n if (!this.client.signingKey) {\n throw new Error(\n `No signing key found in client options or ${envKeys.InngestSigningKey} env var. Find your keys at https://app.inngest.com/env/production/manage/signing-key`,\n );\n }\n\n // If we're here, we're in production; lack of a req signature is an error.\n if (!sig) {\n throw new Error(`No ${headerKeys.Signature} provided`);\n }\n\n // Validate the signature\n return {\n success: true,\n keyUsed: await new RequestSignature(sig).verifySignature({\n body,\n allowExpiredSignatures: this.allowExpiredSignatures,\n signingKey: this.client.signingKey,\n signingKeyFallback: this.client.signingKeyFallback,\n logger: this.client[internalLoggerSymbol],\n }),\n };\n } catch (err) {\n return { success: false, err: err as Error };\n }\n }\n\n protected async getResponseSignature(\n key: string,\n body: string,\n ): Promise<string> {\n const now = Math.round(Date.now() / 1000);\n const mac = await signDataWithKey(\n body,\n key,\n now.toString(),\n this.client[internalLoggerSymbol],\n );\n\n return `t=${now}&s=${mac}`;\n }\n}\n\n/**\n * @internal Exported for testing; not part of the public API.\n */\nexport class RequestSignature {\n public timestamp: string;\n public signature: string;\n\n constructor(sig: string) {\n const params = new URLSearchParams(sig);\n this.timestamp = params.get(\"t\") || \"\";\n this.signature = params.get(\"s\") || \"\";\n\n if (!this.timestamp || !this.signature) {\n throw new Error(`Invalid ${headerKeys.Signature} provided`);\n }\n }\n\n private hasExpired(allowExpiredSignatures?: boolean) {\n if (allowExpiredSignatures) {\n return false;\n }\n\n const ts = Number.parseInt(this.timestamp, 10);\n if (!Number.isFinite(ts)) {\n return true;\n }\n\n const delta = Date.now() - ts * 1000;\n // Clamp both ends: negative delta (future-skewed `t`) would otherwise give\n // captured requests an unbounded replay\n return Math.abs(delta) > 1000 * 60 * 5;\n }\n\n async #verifySignature({\n body,\n signingKey,\n allowExpiredSignatures,\n logger,\n }: {\n body: unknown;\n signingKey: string;\n allowExpiredSignatures: boolean;\n logger: Logger;\n }): Promise<void> {\n if (this.hasExpired(allowExpiredSignatures)) {\n throw new Error(\"Signature has expired\");\n }\n\n const mac = await signDataWithKey(body, signingKey, this.timestamp, logger);\n if (!timingSafeEqual(mac, this.signature)) {\n throw new Error(\"Invalid signature\");\n }\n }\n\n public async verifySignature({\n body,\n signingKey,\n signingKeyFallback,\n allowExpiredSignatures,\n logger,\n }: {\n body: unknown;\n signingKey: string;\n signingKeyFallback: string | undefined;\n allowExpiredSignatures: boolean;\n logger: Logger;\n }): Promise<string> {\n try {\n await this.#verifySignature({\n body,\n signingKey,\n allowExpiredSignatures,\n logger,\n });\n\n return signingKey;\n } catch (err) {\n if (!signingKeyFallback) {\n throw err;\n }\n\n await this.#verifySignature({\n body,\n signingKey: signingKeyFallback,\n allowExpiredSignatures,\n logger,\n });\n\n return signingKeyFallback;\n }\n }\n}\n\n/**\n * The broad definition of a handler passed when instantiating an\n * {@link InngestCommHandler} instance.\n */\nexport type Handler<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Input extends any[] = any[],\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n Output = any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n StreamOutput = any,\n> = (...args: Input) => HandlerResponse<Output, StreamOutput>;\n\n// biome-ignore lint/suspicious/noExplicitAny: intentional\nexport type HandlerResponse<Output = any, StreamOutput = any> = {\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n body: () => MaybePromise<any>;\n env?: () => MaybePromise<Env | undefined>;\n headers: (key: string) => MaybePromise<string | null | undefined>;\n\n method: () => MaybePromise<string>;\n queryString?: (\n key: string,\n url: URL,\n ) => MaybePromise<string | null | undefined>;\n url: () => MaybePromise<URL>;\n\n /**\n * The `transformResponse` function receives the output of the Inngest SDK and\n * can decide how to package up that information to appropriately return the\n * information to Inngest.\n *\n * Mostly, this is taking the given parameters and returning a new `Response`.\n *\n * The function is passed an {@link ActionResponse}, an object containing a\n * `status` code, a `headers` object, and a stringified `body`. This ensures\n * you can appropriately handle the response, including use of any required\n * parameters such as `res` in Express-/Connect-like frameworks.\n */\n transformResponse: (res: ActionResponse<string>) => Output;\n\n /**\n * The `transformStreamingResponse` function, if defined, declares that this\n * handler supports streaming responses back to Inngest. This is useful for\n * functions that are expected to take a long time, as edge streaming can\n * often circumvent restrictive request timeouts and other limitations.\n *\n * If your handler does not support streaming, do not define this function.\n *\n * It receives the output of the Inngest SDK and can decide how to package\n * up that information to appropriately return the information in a stream\n * to Inngest.\n *\n * Mostly, this is taking the given parameters and returning a new `Response`.\n *\n * The function is passed an {@link ActionResponse}, an object containing a\n * `status` code, a `headers` object, and `body`, a `ReadableStream`. This\n * ensures you can appropriately handle the response, including use of any\n * required parameters such as `res` in Express-/Connect-like frameworks.\n */\n transformStreamingResponse?: (\n res: ActionResponse<ReadableStream>,\n ) => StreamOutput;\n\n /**\n * TODO Needed to give folks a chance to wrap arguments if they need to in\n * order to extract the request body so that it can be sent back to Inngest\n * during either sync or async calls.\n *\n * This is because usually they do not interact directly with e.g. the\n * `Response` object, but with sync mode they do, so we need to provide hooks\n * to let us access the body.\n */\n experimentalTransformSyncRequest?: (\n ...args: unknown[]\n ) => MaybePromise<unknown>;\n\n /**\n * TODO Needed to give folks a chance to transform the response from their own\n * code to an Inngestish response. This is only needed so that sync mode can\n * checkpoint the response if we've gone through the entire run with no\n * interruptions.\n *\n * Because of its location when being specified, we have scoped access to the\n * `reqArgs` (e.g. `req` and `res`), so we don't need to pass them here.\n */\n experimentalTransformSyncResponse?: (\n data: unknown,\n ) => MaybePromise<Omit<ActionResponse, \"version\">>;\n};\n\n/**\n * The response from the Inngest SDK before it is transformed in to a\n * framework-compatible response by an {@link InngestCommHandler} instance.\n */\nexport interface ActionResponse<\n TBody extends string | ReadableStream = string,\n> {\n /**\n * The HTTP status code to return.\n */\n status: number;\n\n /**\n * The headers to return in the response.\n */\n headers: Record<string, string>;\n\n /**\n * A stringified body to return.\n */\n body: TBody;\n\n /**\n * The version of the execution engine that was used to run this action.\n *\n * If the action didn't use the execution engine (for example, a GET request\n * as a health check) or would have but errored before reaching it, this will\n * be `undefined`.\n *\n * If the version should be entirely omitted from the response (for example,\n * when sending preliminary headers when streaming), this will be `null`.\n */\n version: ExecutionVersion | null | undefined;\n}\n\n/**\n * A version of {@link HandlerResponse} where each function is safely\n * promisified and requires a reason for each access.\n *\n * This enables us to provide accurate errors for each access without having to\n * wrap every access in a try/catch.\n */\nexport type ActionHandlerResponseWithErrors = {\n [K in keyof HandlerResponse]: NonNullable<HandlerResponse[K]> extends (\n ...args: infer Args\n ) => infer R\n ? R extends MaybePromise<infer PR>\n ? (errMessage: string, ...args: Args) => Promise<PR>\n : (errMessage: string, ...args: Args) => Promise<R>\n : HandlerResponse[K];\n};\n\n/**\n * A version of {@link ActionHandlerResponseWithErrors} that includes helper\n * functions that provide sensible defaults on top of the direct access given\n * from the bare response.\n */\nexport interface HandlerResponseWithErrors\n extends ActionHandlerResponseWithErrors {\n /**\n * Fetch a query string value from the request. If no `querystring` action has\n * been provided by the `serve()` handler, this will fall back to using the\n * provided URL present in the request to parse the query string from instead.\n */\n queryStringWithDefaults: (\n reason: string,\n key: string,\n ) => Promise<string | undefined>;\n}\n"],"mappings":"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"}