inngest
Version:
Official SDK for Inngest.com. Inngest is the reliability layer for modern applications. Inngest combines durable execution, events, and queues into a zero-infra platform with built-in observability.
1 lines • 58.8 kB
Source Map (JSON)
{"version":3,"file":"types.cjs","names":["z","maybeJsonErrorSchema: z.ZodType<{\n name: string;\n message: string;\n stack?: string;\n cause?: unknown;\n}>","defaultCheckpointingOptions: InternalCheckpointingOptions"],"sources":["../src/types.ts"],"sourcesContent":["/**\n * Internal types and schemas used throughout the Inngest SDK.\n *\n * Note that types intended to be imported and utilized in userland code will be\n * exported from the main entrypoint of the SDK, `inngest`; importing types\n * directly from this file may result in breaking changes in non-major bumps as\n * only those exported from `inngest` are considered stable.\n *\n * @module\n */\n\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { z } from \"zod/v3\";\nimport type { Inngest } from \"./components/Inngest.ts\";\nimport type { InngestEndpointAdapter } from \"./components/InngestEndpointAdapter.ts\";\nimport type { InngestFunction } from \"./components/InngestFunction.ts\";\nimport type { InngestFunctionReference } from \"./components/InngestFunctionReference.ts\";\nimport type { createGroupTools } from \"./components/InngestGroupTools.ts\";\nimport type { createStepTools } from \"./components/InngestStepTools.ts\";\nimport type { Middleware } from \"./components/middleware/index.ts\";\nimport type {\n EventType,\n EventTypeWithAnySchema,\n} from \"./components/triggers/triggers.ts\";\nimport type { internalEvents } from \"./helpers/consts.ts\";\nimport type { Jsonify } from \"./helpers/jsonify.ts\";\nimport type { GoInterval } from \"./helpers/promises.ts\";\nimport type * as Temporal from \"./helpers/temporal.ts\";\nimport type {\n AsTuple,\n IsEqual,\n IsNever,\n Public,\n Simplify,\n} from \"./helpers/types.ts\";\nimport type { Logger } from \"./middleware/logger.ts\";\n\nexport type { Jsonify } from \"./helpers/jsonify.ts\";\nexport type { SimplifyDeep } from \"./helpers/types.ts\";\n\nconst baseJsonErrorSchema = z.object({\n name: z.string().trim().optional(),\n error: z.string().trim().optional(),\n message: z.string().trim().optional(),\n stack: z.string().trim().optional(),\n});\n\nconst maybeJsonErrorSchema: z.ZodType<{\n name: string;\n message: string;\n stack?: string;\n cause?: unknown;\n}> = z.lazy(() =>\n z.object({\n name: z.string().trim(),\n message: z.string().trim(),\n stack: z.string().trim().optional(),\n cause: z.union([maybeJsonErrorSchema, z.unknown()]).optional(),\n }),\n);\n\nexport type JsonError = z.infer<typeof baseJsonErrorSchema> & {\n name: string;\n message: string;\n cause?: unknown;\n};\n\nexport const jsonErrorSchema = baseJsonErrorSchema\n .extend({\n cause: z.union([maybeJsonErrorSchema, z.unknown()]).optional(),\n })\n .passthrough()\n .catch({})\n .transform((val) => {\n return {\n ...val,\n name: val.name || \"Error\",\n message: val.message || val.error || \"Unknown error\",\n stack: val.stack,\n };\n }) as z.ZodType<JsonError>;\n\n/**\n * The payload for an API endpoint running steps.\n */\nexport type APIStepPayload = {\n name: `${internalEvents.HttpRequest}`;\n data: {\n /**\n * The domain that served the original request.\n */\n domain: string;\n\n /**\n * The method used to trigger the original request.\n */\n method: string;\n\n /**\n * The URL path of the original request.\n */\n path: string;\n\n /**\n * The IP that made the original request, fetched from headers.\n */\n ip: string;\n\n /**\n * The \"Content-Type\" header of the original request.\n */\n content_type: string;\n\n /**\n * The query parameters of the original request, as a single string without\n * the leading `\"?\"`.\n */\n query_params: string;\n\n /**\n * The body of the original request.\n */\n body?: string;\n\n /**\n * An optional function ID to use for this endpoint. If not provided,\n * Inngest will generate a function ID based on the method and path, e.g.\n * `\"GET /api/hello\"`.\n */\n fn?: string; // maybe explicit fn ID from user, else empty\n };\n};\n\n/**\n * The payload for an internal Inngest event that is sent when a function fails.\n *\n * @public\n */\nexport type FailureEventPayload<P extends EventPayload = EventPayload> = {\n name: `${internalEvents.FunctionFailed}`;\n data: {\n function_id: string;\n run_id: string;\n error: z.output<typeof jsonErrorSchema>;\n event: P;\n };\n};\n\n/**\n * Context arguments specific to a failure event.\n *\n * @public\n */\nexport type FailureEventArgs<P extends EventPayload = EventPayload> = {\n /**\n * The event data present in the payload.\n */\n event: FailureEventPayload<P>;\n\n /**\n * The final error that caused this function to exhaust all retries.\n */\n error: Error;\n};\n\n/**\n * The payload for an internal Inngest event that is sent when a function\n * finishes, either by completing successfully or failing.\n *\n * @public\n */\nexport type FinishedEventPayload = {\n name: `${internalEvents.FunctionFinished}`;\n data: {\n function_id: string;\n run_id: string;\n correlation_id?: string;\n } & (\n | {\n error: z.output<typeof jsonErrorSchema>;\n }\n | {\n result: unknown;\n }\n );\n};\n\n/**\n * The payload for an internal Inngest event that is sent when a function is\n * cancelled.\n */\nexport type CancelledEventPayload = {\n name: `${internalEvents.FunctionCancelled}`;\n data: {\n function_id: string;\n run_id: string;\n correlation_id?: string;\n };\n};\n\n/**\n * The payload for any generic function invocation event. In practice, the event\n * data will be more specific to the function being invoked.\n *\n * @public\n */\nexport type InvokedEventPayload = Simplify<\n Omit<EventPayload, \"name\"> & {\n name: `${internalEvents.FunctionInvoked}`;\n }\n>;\n\n/**\n * The payload for the event sent to a function when it is triggered by a cron.\n *\n * @public\n */\nexport type ScheduledTimerEventPayload = Simplify<\n Omit<EventPayload, \"name\" | \"data\" | \"id\"> & {\n name: `${internalEvents.ScheduledTimer}`;\n data: {\n cron: string;\n };\n id: string;\n }\n>;\n\n/**\n * Unique codes for the different types of operation that can be sent to Inngest\n * from SDK step functions.\n */\nexport enum StepOpCode {\n WaitForSignal = \"WaitForSignal\",\n\n WaitForEvent = \"WaitForEvent\",\n\n /**\n * Legacy equivalent to `\"StepRun\"`. Has mixed data wrapping (e.g. `data` or\n * `data.data` depending on SDK version), so this is phased out in favour of\n * `\"StepRun\"`, which never wraps.\n *\n * Note that it is still used for v0 executions for backwards compatibility.\n *\n * @deprecated Only used for v0 executions; use `\"StepRun\"` instead.\n */\n Step = \"Step\",\n StepRun = \"StepRun\",\n StepError = \"StepError\",\n StepFailed = \"StepFailed\",\n StepPlanned = \"StepPlanned\",\n Sleep = \"Sleep\",\n\n /**\n * Used to signify that the executor has requested that a step run, but we\n * could not find that step.\n *\n * This is likely indicative that a step was renamed or removed from the\n * function.\n */\n StepNotFound = \"StepNotFound\",\n\n InvokeFunction = \"InvokeFunction\",\n AiGateway = \"AIGateway\",\n Gateway = \"Gateway\",\n\n RunComplete = \"RunComplete\",\n DiscoveryRequest = \"DiscoveryRequest\",\n}\n\n/**\n * StepModes are used to specify how the SDK should execute a function.\n */\nexport enum StepMode {\n /**\n * A synchronous method of execution, where steps are executed immediately and\n * their results are \"checkpointed\" back to Inngest in real-time.\n */\n Sync = \"sync\",\n\n /**\n * The traditional, background method of execution, where all steps are queued\n * and executed asynchronously and always triggered by Inngest.\n */\n Async = \"async\",\n\n /**\n * The traditional, background method of execution, but step results are\n * checkpointed when they can be to reduce latency and the number of requests\n * being sent back and forth between Inngest and the SDK.\n */\n AsyncCheckpointing = \"async_checkpointing\",\n}\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 */\nexport enum AsyncResponseType {\n /**\n * When switching to {@link StepMode.Async}, respond with a 302 redirect which\n * will end the request once the run has completed asynchronously in the\n * background.\n */\n Redirect = \"redirect\",\n\n /**\n * When switching to {@link StepMode.Async}, respond with a token and run ID\n * which can be used to poll for the status of the run.\n */\n Token = \"token\",\n\n /**\n * TODO Comment\n */\n // Custom = \"custom\",\n}\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 */\nexport type AsyncResponseValue =\n | AsyncResponseType.Redirect\n | AsyncResponseType.Token;\n// | (() => null);\n\n/**\n * The shape of a single operation in a step function. Used to communicate\n * desired and received operations to Inngest.\n */\nexport type Op = {\n /**\n * The unique code for this operation.\n */\n op: StepOpCode;\n\n /**\n * What {@link StepMode} this step supports. If a step is marked as supporting\n * {@link StepMode.Async} we must be in (or switch to) async mode in order to\n * execute it.\n */\n mode: StepMode;\n\n /**\n * The unhashed step name for this operation. This is a legacy field that is\n * sometimes used for critical data, like the sleep duration for\n * `step.sleep()`.\n *\n * @deprecated For display name, use `displayName` instead.\n */\n name?: string;\n\n /**\n * An optional name for this step that can be used to display in the Inngest\n * UI.\n */\n displayName?: string;\n\n /**\n * Any additional data required for this operation to send to Inngest. This\n * is not compared when confirming that the operation was completed; use `id`\n * for this.\n */\n opts?: Record<string, unknown>;\n\n /**\n * Any data present for this operation. If data is present, this operation is\n * treated as completed.\n */\n data?: unknown;\n\n /**\n * An error present for this operation. If an error is present, this operation\n * is treated as completed, but failed. When this is read from the op stack,\n * the SDK will throw the error via a promise rejection when it is read.\n *\n * This allows users to handle step failures using common tools such as\n * try/catch or `.catch()`.\n */\n error?: unknown;\n\n /**\n * Extra info used to annotate spans associated with this operation.\n */\n userland: OpUserland;\n\n /**\n * Golang-compatibile `interval.Interval` timing information for this operation.\n */\n timing?: GoInterval;\n};\n\n/**\n * Extra info attached to an operation.\n */\nexport type OpUserland = {\n /**\n * The unhashed, user-defined ID of the step.\n */\n id: string;\n /**\n * The auto-incremented index for repeated steps (if repeated).\n */\n index?: number;\n};\n\nexport const incomingOpSchema = z.object({\n id: z.string().min(1),\n data: z.any().optional(),\n error: z.any().optional(),\n input: z.any().optional(),\n});\n\nexport type IncomingOp = z.output<typeof incomingOpSchema>;\n\n/**\n * The shape of a step operation that is sent to an Inngest Server from an SDK.\n *\n * @public\n */\nexport type OutgoingOp = Pick<\n Omit<HashedOp, \"userland\"> & { userland?: OpUserland },\n | \"id\"\n | \"op\"\n | \"name\"\n | \"opts\"\n | \"data\"\n | \"error\"\n | \"displayName\"\n | \"userland\"\n | \"timing\"\n>;\n\n/**\n * The shape of a hashed operation in a step function. Used to communicate\n * desired and received operations to Inngest.\n */\nexport type HashedOp = Op & {\n /**\n * The hashed identifier for this operation, used to confirm that the\n * operation was completed when it is received from Inngest.\n */\n id: string;\n};\n\n/**\n * A helper type to represent a stack of operations that will accumulate\n * throughout a step function's run. This stack contains an object of\n * op hashes to data.\n */\nexport type OpStack = IncomingOp[];\n\n/**\n * A function that can be used to submit an operation to Inngest internally.\n */\nexport type SubmitOpFn = (op: Op) => void;\n\n/**\n * A sleep-compatible time string such as `\"1h30m15s\"` that can be sent to\n * Inngest to sleep for a given amount of time.\n *\n * This type includes an empty string too, so make sure to exclude that via\n * `Exclude<TimeStr, \"\">` if you don't want to allow empty strings.\n *\n * @public\n */\nexport type TimeStr = `${`${number}w` | \"\"}${`${number}d` | \"\"}${\n | `${number}h`\n | \"\"}${`${number}m` | \"\"}${`${number}s` | \"\"}`;\n\nexport type TimeStrBatch = `${`${number}s`}`;\n\n/**\n * Mutates an {@link EventPayload} `T` to include invocation events.\n */\nexport type WithInvocation<T extends EventPayload> = Simplify<\n { name: T[\"name\"] | `${internalEvents.FunctionInvoked}` } & Omit<T, \"name\">\n>;\n\n/**\n * Base context object, omitting any extras that may be added by middleware or\n * function configuration.\n *\n * @public\n */\nexport type BaseContext<TClient extends Inngest.Any> = {\n /**\n * The event data present in the payload.\n */\n event: Simplify<EventPayload>;\n events: AsTuple<Simplify<EventPayload>>;\n\n /**\n * The run ID for the current function execution\n */\n runId: string;\n\n step: ReturnType<typeof createStepTools<TClient>>;\n\n /**\n * Tools for grouping and coordinating steps.\n */\n group: ReturnType<typeof createGroupTools>;\n\n /**\n * The current zero-indexed attempt number for this function execution. The\n * first attempt will be `0`, the second `1`, and so on. The attempt number\n * is incremented every time the function throws an error and is retried.\n */\n attempt: number;\n\n /**\n * The maximum number of attempts allowed for this function.\n */\n maxAttempts?: number;\n};\n\n/**\n * Builds a context object for an Inngest handler, optionally overriding some\n * keys.\n *\n * @internal\n */\nexport type Context<\n TClient extends Inngest.Any = Inngest.Any,\n TOverrides extends Record<string, unknown> = Record<never, never>,\n> = Omit<BaseContext<TClient>, keyof TOverrides> & TOverrides;\n\n/**\n * Builds a context object for an Inngest handler, optionally overriding some\n * keys.\n *\n * @internal\n */\nexport namespace Context {\n /**\n * Represents any `Context` object, regardless of generics and inference.\n */\n export type Any = Context;\n}\n\n/**\n * The shape of a Inngest function, taking in event, step, ctx, and step\n * tooling.\n *\n * @public\n */\nexport type Handler<\n TClient extends Inngest.Any,\n TOverrides extends Record<string, unknown> = Record<never, never>,\n> = (\n /**\n * The context argument provides access to all data and tooling available to\n * the function.\n */\n ctx: Context<TClient, TOverrides>,\n) => unknown;\n\n/**\n * The shape of a Inngest function, taking in event, step, ctx, and step\n * tooling.\n *\n * @public\n */\nexport namespace Handler {\n /**\n * Represents any `Handler`, regardless of generics and inference.\n */\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n export type Any = Handler<Inngest.Any, any>;\n}\n\n/**\n * The shape of a single event's payload without any fields used to identify the\n * actual event being sent.\n *\n * This is used to represent an event payload when invoking a function, as the\n * event name is not known or needed.\n */\n// biome-ignore lint/suspicious/noExplicitAny: intentional\nexport interface MinimalEventPayload<TData = any> {\n /**\n * A unique id used to idempotently process a given event payload.\n *\n * Set this when sending events to ensure that the event is only processed\n * once; if an event with the same ID is sent again, it will not invoke\n * functions.\n */\n id?: string;\n\n /**\n * Any data pertinent to the event\n */\n data?: TData;\n\n /**\n * A specific event schema version\n * (optional)\n */\n v?: string;\n}\n\n/**\n * The shape of a single event's payload. It should be extended to enforce\n * adherence to given events and not used as a method of creating them (i.e. as\n * a generic).\n *\n * @public\n */\n// biome-ignore lint/suspicious/noExplicitAny: intentional\nexport interface EventPayload<TData = any> extends MinimalEventPayload<TData> {\n /**\n * A unique identifier for the type of event. We recommend using lowercase dot\n * notation for names, prepending `prefixes/` with a slash for organization.\n *\n * e.g. `cloudwatch/alarms/triggered`, `cart/session.created`\n */\n name: string;\n\n /**\n * An integer representing the milliseconds since the unix epoch at which this\n * event occurred.\n *\n * Defaults to the current time.\n * (optional)\n */\n ts?: number;\n}\n\nexport const sendEventResponseSchema = z.object({\n /**\n * Event IDs\n */\n ids: z.array(z.string()).default([]),\n\n /**\n * HTTP Status Code. Will be undefined if no request was sent.\n */\n status: z.number().default(0),\n\n /**\n * Error message. Will be undefined if no error occurred.\n */\n error: z.string().optional(),\n});\n\n/**\n * The response from the Inngest Event API\n */\nexport type SendEventResponse = z.output<typeof sendEventResponseSchema>;\n\n/**\n * The response in code from sending an event to Inngest.\n *\n * @public\n */\nexport type SendEventBaseOutput = {\n ids: SendEventResponse[\"ids\"];\n};\n\nexport type SendEventOutput<TOpts extends ClientOptions> = Omit<\n SendEventBaseOutput,\n keyof SendEventOutputWithMiddleware<TOpts>\n> &\n SendEventOutputWithMiddleware<TOpts>;\n\nexport type SendEventOutputWithMiddleware<_TOpts extends ClientOptions> =\n SendEventBaseOutput;\n\n/**\n * Discriminator for which output transform to extract from middleware.\n */\ntype TransformKind = \"functionOutputTransform\" | \"stepOutputTransform\";\n\n/**\n * Extract the `functionOutputTransform` from a middleware class.\n */\ntype GetMiddlewareRunTransformer<TMw> = TMw extends Middleware.Class\n ? InstanceType<TMw> extends {\n functionOutputTransform: infer TTransform extends\n Middleware.StaticTransform;\n }\n ? TTransform\n : Middleware.DefaultStaticTransform\n : Middleware.DefaultStaticTransform;\n\n/**\n * Extract the `stepOutputTransform` from a middleware class.\n */\ntype GetMiddlewareStepTransformer<TMw> = TMw extends Middleware.Class\n ? InstanceType<TMw> extends {\n stepOutputTransform: infer TTransform extends Middleware.StaticTransform;\n }\n ? TTransform\n : Middleware.DefaultStaticTransform\n : Middleware.DefaultStaticTransform;\n\n/**\n * Dispatch to the correct transformer extractor based on `TKind`.\n */\ntype GetMiddlewareTransformerByKind<\n TMw,\n TKind extends TransformKind,\n> = TKind extends \"functionOutputTransform\"\n ? GetMiddlewareRunTransformer<TMw>\n : GetMiddlewareStepTransformer<TMw>;\n\n/**\n * Apply all middleware transforms in sequence.\n * Each middleware's transform is applied to the result of the previous one.\n * When no middleware is provided, applies Jsonify as the default transform.\n */\nexport type ApplyAllMiddlewareTransforms<\n TMw extends Middleware.Class[] | undefined,\n T,\n TKind extends TransformKind = \"stepOutputTransform\",\n> = TMw extends [Middleware.Class, ...Middleware.Class[]]\n ? ApplyMiddlewareTransformsInternal<TMw, T, TKind>\n : Jsonify<T>; // No middleware or empty array - apply default Jsonify\n\n/**\n * Internal helper that recursively applies middleware transforms.\n * Does NOT apply Jsonify at the end, as that's only for the no-middleware case.\n *\n * Processes from the end of the array first to match the runtime onion model:\n * the last middleware in the array is innermost and transforms first, while the\n * first middleware is outermost and transforms last. For `[MW1, MW2]` with\n * input `T`, this gives `MW1(MW2(T))`.\n */\ntype ApplyMiddlewareTransformsInternal<\n TMw extends Middleware.Class[] | undefined,\n T,\n TKind extends TransformKind,\n> = TMw extends [...infer Rest extends Middleware.Class[], infer Last]\n ? ApplyMiddlewareTransformsInternal<\n Rest,\n ApplyMiddlewareStaticTransform<\n GetMiddlewareTransformerByKind<Last, TKind>,\n T\n >,\n TKind\n >\n : T;\n\n/**\n * Apply the output transformation using the In/Out interface pattern.\n *\n * @example\n * ```ts\n * interface PreserveDate extends MiddlewareStaticTransform {\n * Out: this[\"In\"] extends Date ? Date : Jsonify<this[\"In\"]>;\n * }\n *\n * // ApplyStaticTransform<PreserveDate, Date> = Date\n * ```\n */\nexport type ApplyMiddlewareStaticTransform<\n TTransformer extends { In: unknown; Out: unknown },\n T,\n> = (TTransformer & { In: T })[\"Out\"];\n\n/**\n * Extract the context extensions from a middleware class (constructor).\n * Looks at the return type of `transformFunctionInput` and extracts additional\n * properties on `ctx` (excluding base `TransformFunctionInputArgs[\"ctx\"]` properties).\n */\ntype GetMiddlewareCtxExtensions<T> = T extends Middleware.Class\n ? InstanceType<T> extends {\n transformFunctionInput(arg: Middleware.TransformFunctionInputArgs): {\n ctx: infer TCtx;\n };\n }\n ? Omit<TCtx, keyof Middleware.TransformFunctionInputArgs[\"ctx\"]>\n : {}\n : {};\n\n/**\n * Apply all middleware context extensions.\n * Each middleware's ctx extensions are merged into the final type.\n * When no middleware is provided, returns an empty object.\n */\nexport type ApplyAllMiddlewareCtxExtensions<\n TMw extends Middleware.Class[] | undefined,\n> = TMw extends [Middleware.Class, ...Middleware.Class[]]\n ? ApplyMiddlewareCtxExtensionsInternal<TMw>\n : {};\n\n/**\n * Internal helper that recursively merges middleware ctx extensions.\n */\ntype ApplyMiddlewareCtxExtensionsInternal<\n TMw extends Middleware.Class[] | undefined,\n> = TMw extends [infer First, ...infer Rest extends Middleware.Class[]]\n ? GetMiddlewareCtxExtensions<First> &\n ApplyMiddlewareCtxExtensionsInternal<Rest>\n : {};\n\n/**\n * Extract the step extensions from a middleware class (constructor).\n * Looks at the return type of `transformFunctionInput` and extracts additional\n * properties on `ctx.step` (excluding base `StepTools` properties).\n */\ntype GetMiddlewareStepExtensions<T> = T extends Middleware.Class\n ? InstanceType<T> extends {\n transformFunctionInput(arg: Middleware.TransformFunctionInputArgs): {\n ctx: { step: infer TStep };\n };\n }\n ? Omit<TStep, keyof Middleware.StepTools>\n : {}\n : {};\n\n/**\n * Apply all middleware step extensions.\n * Each middleware's step extensions are merged into the final type.\n * When no middleware is provided, returns an empty object.\n */\nexport type ApplyAllMiddlewareStepExtensions<\n TMw extends Middleware.Class[] | undefined,\n> = TMw extends [Middleware.Class, ...Middleware.Class[]]\n ? ApplyMiddlewareStepExtensionsInternal<TMw>\n : {};\n\n/**\n * Internal helper that recursively merges middleware step extensions.\n */\ntype ApplyMiddlewareStepExtensionsInternal<\n TMw extends Middleware.Class[] | undefined,\n> = TMw extends [infer First, ...infer Rest extends Middleware.Class[]]\n ? GetMiddlewareStepExtensions<First> &\n ApplyMiddlewareStepExtensionsInternal<Rest>\n : {};\n\n/**\n * An HTTP-like, standardised response format that allows Inngest to help\n * orchestrate steps and retries.\n *\n * @internal\n */\nexport interface Response {\n /**\n * A step response must contain an HTTP status code.\n *\n * A `2xx` response indicates success; this is not a failure and no retry is\n * necessary.\n *\n * A `4xx` response indicates a bad request; this step will not be retried as\n * it is deemed irrecoverable. Examples of this might be an event with\n * insufficient data or concerning a user that no longer exists.\n *\n * A `5xx` status indicates a temporary internal error; this will be retried\n * according to the step and function's retry policy (3 times, by default).\n *\n * {@link https://www.inngest.com/docs/functions/function-input-and-output#response-format}\n * {@link https://www.inngest.com/docs/functions/retries}\n */\n status: number;\n\n /**\n * The output of the function - the `body` - can be any arbitrary\n * JSON-compatible data. It is then usable by any future steps.\n *\n * {@link https://www.inngest.com/docs/functions/function-input-and-output#response-format}\n */\n body?: unknown;\n}\n\n/**\n * A single step within a function.\n *\n * @internal\n */\nexport type Step<TContext = unknown> = (\n /**\n * The context for this step, including the triggering event and any previous\n * step output.\n */\n context: TContext,\n) => Promise<Response> | Response;\n\n/**\n * A set of options for configuring the Inngest client.\n *\n * @public\n */\nexport interface ClientOptions {\n /**\n * The ID of this instance, most commonly a reference to the application it\n * resides in.\n *\n * The ID of your client should remain the same for its lifetime; if you'd\n * like to change the name of your client as it appears in the Inngest UI,\n * change the `name` property instead.\n */\n id: string;\n\n /**\n * Inngest event key, used to send events to Inngest Cloud. If not provided,\n * will search for the `INNGEST_EVENT_KEY` environment variable. If neither\n * can be found, however, a warning will be shown and any attempts to send\n * events will throw an error.\n */\n eventKey?: string;\n\n /**\n * The base URL to use when contacting Inngest.\n *\n * Defaults to https://inn.gs/ for sending events and https://api.inngest.com\n * for all other communication with Inngest.\n */\n baseUrl?: string;\n\n /**\n * If provided, will override the used `fetch` implementation. Useful for\n * giving the library a particular implementation if accessing it is not done\n * via globals.\n *\n * By default the library will try to use the native Web API fetch, falling\n * back to a Node implementation if no global fetch can be found.\n *\n * If you wish to specify your own fetch, make sure that you preserve its\n * binding, either by using `.bind` or by wrapping it in an anonymous\n * function.\n */\n fetch?: typeof fetch;\n\n /**\n * The Inngest environment to send events to. Defaults to whichever\n * environment this client's event key is associated with.\n *\n * It's likely you never need to change this unless you're trying to sync\n * multiple systems together using branch names.\n */\n env?: string;\n\n /**\n * The logger provided by the user.\n * The user can passed in their winston, pino, and other loggers for\n * handling log delivery to external services.\n *\n * The provider logger is expected to implement the following API interfaces\n * - .info()\n * - .warn()\n * - .debug()\n * - .error()\n * which most loggers already do.\n *\n * Defaults to a dummy logger that just log things to the console if nothing is provided.\n */\n logger?: Logger;\n\n /**\n * A separate logger for SDK internal messages (registration, middleware\n * errors, request parsing, etc.). If not provided, falls back to `logger`.\n *\n * Use this to route SDK internals to a different destination or to tag them\n * for filtering, e.g. `pino.child({ component: \"inngest\" })`.\n *\n * User function logs via `ctx.logger` are not affected.\n */\n internalLogger?: Logger;\n\n /**\n * Middleware classes that provide simpler hooks for common operations.\n * Each class is instantiated fresh per-request so that middleware can safely\n * use `this` for request-scoped state.\n */\n middleware?: Middleware.Class[];\n\n /**\n * Can be used to explicitly set the client to Development Mode, which will\n * turn off signature verification and default to using a local URL to access\n * a local Dev Server.\n *\n * This is useful for forcing the client to use a local Dev Server while also\n * running in a production-like environment.\n */\n isDev?: boolean;\n\n /**\n * The application-specific version identifier. This can be an arbitrary value\n * such as a version string, a Git commit SHA, or any other unique identifier.\n */\n appVersion?: string;\n\n /**\n * Optimizes parallel steps to reduce traffic during `Promise` resolution,\n * reducing time and requests per run. `Promise.*()` waits for all promises\n * to settle before resolving. Use `group.parallel()` for `Promise.race()`\n * semantics.\n *\n * @default true\n */\n optimizeParallelism?: boolean;\n\n /**\n * Whether or not to use checkpointing by default for executions of functions\n * created using this client.\n *\n * If `true`, enables checkpointing with default settings, which is a safe,\n * blocking version of checkpointing, where we check in with Inngest after\n * every step is run.\n *\n * If an object, you can tweak the settings to batch, set a maximum runtime\n * before going async, and more. Note that if your server dies before the\n * checkpoint completes, step data will be lost and steps will be rerun.\n *\n * We recommend starting with the default `true` configuration and only tweak\n * the parameters directly if necessary.\n *\n * @deprecated Use `checkpointing` instead.\n */\n experimentalCheckpointing?: CheckpointingOptions;\n\n /**\n * Whether or not to use checkpointing by default for executions of functions\n * created using this client.\n *\n * If `false`, disables checkpointing.\n *\n * If `true`, enables checkpointing with default settings, which is a safe,\n * blocking version of checkpointing, where we check in with Inngest after\n * every step is run.\n *\n * If an object, you can tweak the settings to batch, set a maximum runtime\n * before going async, and more. Note that if your server dies before the\n * checkpoint completes, step data will be lost and steps will be rerun.\n *\n * We recommend starting with the default `true` configuration and only tweak\n * the parameters directly if necessary.\n *\n * @default true\n */\n checkpointing?: CheckpointingOptions;\n\n /**\n * The signing key used to authenticate requests from Inngest.\n * If not provided, will search for the `INNGEST_SIGNING_KEY` environment variable.\n */\n signingKey?: string;\n\n /**\n * A fallback signing key used to authenticate requests from Inngest during key rotation.\n * If not provided, will search for the `INNGEST_SIGNING_KEY_FALLBACK` environment variable.\n */\n signingKeyFallback?: string;\n\n /**\n * An optional endpoint adapter to use when creating Durable Endpoints using\n * `inngest.endpoint()`.\n */\n endpointAdapter?: InngestEndpointAdapter.Like;\n}\n\nexport type CheckpointingOptions =\n | boolean\n | {\n /**\n * The maximum amount of time the function should be allowed to checkpoint\n * before falling back to async execution.\n *\n * We recommend setting this to a value slightly lower than your\n * platform's request timeout to ensure that functions can complete\n * checkpointing before being forcefully terminated.\n *\n * Set to `0` to disable maximum runtime.\n *\n * @default 0\n */\n maxRuntime?: number | string | Temporal.DurationLike;\n\n /**\n * The number of steps to buffer together before checkpointing. This can\n * help reduce the number of requests made to Inngest when running many\n * steps in sequence.\n *\n * Set to `1` to checkpoint after every step.\n *\n * @default 1\n */\n bufferedSteps?: number;\n\n /**\n * The maximum interval to wait before checkpointing, even if the buffered\n * step count has not been reached.\n */\n maxInterval?: number | string | Temporal.DurationLike;\n };\n\n/**\n * Internal version of {@link CheckpointingOptions} with the `true` option\n * excluded, as that just suggests using the default options.\n */\nexport type InternalCheckpointingOptions = Exclude<\n Required<CheckpointingOptions>,\n boolean\n>;\n\n/**\n * Default config options if `true` has been passed by a user.\n */\nexport const defaultCheckpointingOptions: InternalCheckpointingOptions = {\n bufferedSteps: 1,\n maxRuntime: 0,\n maxInterval: 0,\n};\n\n/**\n * A set of log levels that can be used to control the amount of logging output\n * from various parts of the Inngest library.\n *\n * @public\n */\nexport const logLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"silent\",\n] as const;\n\n/**\n * A set of log levels that can be used to control the amount of logging output\n * from various parts of the Inngest library.\n *\n * @public\n */\nexport type LogLevel = (typeof logLevels)[number];\n\n/**\n * A set of options for configuring the registration of Inngest functions.\n *\n * @public\n */\nexport interface RegisterOptions {\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/rediects).\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 servePath?: 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 serveOrigin?: string;\n\n /**\n * Some serverless providers (especially those with edge compute) may support\n * streaming responses back to Inngest. This can be used to circumvent\n * restrictive request timeouts and other limitations. It is only available if\n * the serve handler being used supports streaming.\n *\n * If this is `\"true\"`, the SDK will attempt to stream responses back\n * to Inngest. If the serve handler does not support streaming, an error will be thrown.\n *\n * If this is `false`, streaming will never be used.\n *\n * Defaults to `false`.\n */\n streaming?: true | false;\n}\n\n/**\n * This schema is used internally to share the shape of a concurrency option\n * when validating config. We cannot add comments to Zod fields, so we just use\n * an extra type check to ensure it matches our exported expectations.\n */\nconst concurrencyOptionSchema = z.strictObject({\n limit: z.number(),\n key: z.string().optional(),\n scope: z.enum([\"fn\", \"env\", \"account\"]).optional(),\n});\n\nconst _checkConcurrencySchemaAligns: IsEqual<\n ConcurrencyOption,\n z.output<typeof concurrencyOptionSchema>\n> = true;\n\nexport interface ConcurrencyOption {\n /**\n * The concurrency limit for this option, adding a limit on how many concurrent\n * steps can execute at once.\n */\n limit: number;\n\n /**\n * An optional concurrency key, as an expression using the common expression language\n * (CEL). The result of this expression is used to create new concurrency groups, or\n * sub-queues, for each function run.\n *\n * The event is passed into this expression as \"event\".\n *\n * Examples:\n * - `event.data.user_id`: this evaluates to the user_id in the event.data object.\n * - `event.data.user_id + \"-\" + event.data.account_id`: creates a new group per user/account\n * - `\"ai\"`: references a custom string\n */\n key?: string;\n\n /**\n * An optional scope for the concurrency group. By default, concurrency limits are\n * scoped to functions - one function's concurrency limits do not impact other functions.\n *\n * Changing this \"scope\" allows concurrency limits to work across environments (eg. production\n * vs branch environments) or across your account (global).\n */\n scope?: \"fn\" | \"env\" | \"account\";\n}\n\n/**\n * Configuration for cancelling a function run based on an incoming event.\n *\n * @public\n */\nexport type Cancellation = {\n /**\n * The name of the event that should cancel the function run.\n */\n event: string | EventTypeWithAnySchema<string>;\n\n /**\n * The expression that must evaluate to true in order to cancel the function run. There\n * are two variables available in this expression:\n * - event, referencing the original function's event trigger\n * - async, referencing the new cancel event.\n *\n * @example\n *\n * Ensures the cancel event's data.user_id field matches the triggering event's data.user_id\n * field:\n *\n * ```ts\n * \"async.data.user_id == event.data.user_id\"\n * ```\n */\n if?: string;\n\n /**\n * If provided, the step function will wait for the incoming event to match\n * particular criteria. If the event does not match, it will be ignored and\n * the step function will wait for another event.\n *\n * It must be a string of a dot-notation field name within both events to\n * compare, e.g. `\"data.id\"` or `\"user.email\"`.\n *\n * ```\n * // Wait for an event where the `user.email` field matches\n * match: \"user.email\"\n * ```\n *\n * All of these are helpers for the `if` option, which allows you to specify\n * a custom condition to check. This can be useful if you need to compare\n * multiple fields or use a more complex condition.\n *\n * See the Inngest expressions docs for more information.\n *\n * {@link https://www.inngest.com/docs/functions/expressions}\n *\n * @deprecated Use `if` instead.\n */\n match?: string;\n\n /**\n * An optional timeout that the cancel is valid for. If this isn't\n * specified, cancellation triggers are valid for up to a year or until the\n * function ends.\n *\n * The time to wait can be specified using a `number` of milliseconds, an\n * `ms`-compatible time string like `\"1 hour\"`, `\"30 mins\"`, or `\"2.5d\"`, or\n * a `Date` object.\n *\n * {@link https://npm.im/ms}\n */\n timeout?: number | string | Date;\n};\n\n/**\n * The response to send to Inngest when pushing function config either directly\n * or when pinged by Inngest Cloud.\n *\n * @internal\n */\nexport interface RegisterRequest {\n /**\n * The API handler's URL to invoke SDK based functions.\n */\n url: string;\n\n /**\n * Response version, allowing Inngest to change any top-level field.\n */\n v: `${number}.${number}`;\n\n /**\n * SDK version from `package.json` for our internal metrics and to warn users\n * they need to upgrade.\n */\n sdk: `js:v${number}.${number}.${number}${\"\" | `-${string}.${number}`}`;\n\n /**\n * The method used to deploy these functions.\n */\n deployType: \"ping\";\n\n /**\n * The name of the framework being used for this instance, e.g. \"nextjs\",\n * \"vercel\", \"netlify\", \"lambda\", etc. Uses the `framework` specified when\n * creating a new `InngestCommHandler`.\n */\n framework: string;\n\n /**\n * The name of this particular app, used for grouping and easier viewing in\n * the UI.\n */\n appName: string;\n\n /**\n * AppVersion represents an optional application version identifier. This should change\n * whenever code within one of your Inngest function or any dependency thereof changes.\n */\n appVersion?: string;\n\n /**\n * The functions available at this particular handler.\n */\n functions: FunctionConfig[];\n\n /**\n * The deploy ID used to identify this particular deployment.\n */\n deployId?: string;\n\n /**\n * Capabilities of the SDK.\n */\n capabilities: Capabilities;\n}\n\nexport interface Capabilities {\n trust_probe: \"v1\";\n connect: \"v1\";\n}\n\nexport interface InBandRegisterRequest\n extends Pick<\n RegisterRequest,\n \"capabilities\" | \"framework\" | \"functions\" | \"sdk\" | \"url\" | \"appVersion\"\n >,\n Pick<AuthenticatedIntrospection, \"sdk_language\" | \"sdk_version\" | \"env\"> {\n /**\n * The ID of the app that this handler is associated with.\n */\n app_id: string;\n\n /**\n * The result of the introspection request.\n */\n inspection: AuthenticatedIntrospection | UnauthenticatedIntrospection;\n\n /**\n * ?\n */\n platform?: string;\n\n /**\n * The person or organization that authored this SDK. Ideally this is\n * synonymous with a GitHub username or organization name.\n */\n sdk_author: \"inngest\";\n}\n\n/**\n * The response to send to the local SDK UI when an introspection request is\n * made.\n *\n * @internal\n */\nexport interface UnauthenticatedIntrospection {\n extra: {\n native_crypto: boolean;\n };\n function_count: number;\n has_event_key: boolean;\n has_signing_key: boolean;\n mode: \"cloud\" | \"dev\";\n schema_version: \"2024-05-24\";\n}\n\nexport interface AuthenticatedIntrospection\n extends Omit<\n UnauthenticatedIntrospection,\n \"authentication_succeeded\" | \"extra\"\n > {\n api_origin: string;\n app_id: string;\n authentication_succeeded: true;\n capabilities: Capabilities;\n env: string | null;\n event_api_origin: string;\n event_key_hash: string | null;\n extra: {\n is_streaming: boolean;\n native_crypto: boolean;\n };\n framework: string;\n sdk_language: string;\n sdk_version: string;\n serve_origin: string | null;\n serve_path: string | null;\n signing_key_fallback_hash: string | null;\n signing_key_hash: string | null;\n}\n\n/**\n * The schema used to represent an individual function being synced with\n * Inngest.\n *\n * Note that this should only be used to validate the shape of a config object\n * and not used for feature compatibility, such as feature X being exclusive\n * with feature Y; these should be handled on the Inngest side.\n */\nexport const functionConfigSchema = z.strictObject({\n name: z.string().optional(),\n id: z.string(),\n triggers: z.array(\n z.union([\n z.strictObject({\n event: z.string(),\n expression: z.string().optional(),\n }),\n z.strictObject({\n cron: z.string(),\n }),\n ]),\n ),\n steps: z.record(\n z.strictObject({\n id: z.string(),\n name: z.string(),\n runtime: z.strictObject({\n type: z.union([z.literal(\"http\"), z.literal(\"ws\")]),\n url: z.string(),\n }),\n retries: z\n .strictObject({\n attempts: z.number().optional(),\n })\n .optional(),\n }),\n ),\n idempotency: z.string().optional(),\n batchEvents: z\n .strictObject({\n maxSize: z.number(),\n timeout: z.string(),\n key: z.string().optional(),\n if: z.string().optional(),\n })\n .optional(),\n rateLimit: z\n .strictObject({\n key: z.string().optional(),\n limit: z.number(),\n period: z.string().transform((x) => x as TimeStr),\n })\n .optional(),\n throttle: z\n .strictObject({\n key: z.string().optional(),\n limit: z.number(),\n period: z.string().transform((x) => x as TimeStr),\n burst: z.number().optional(),\n })\n .optional(),\n singleton: z\n .strictObject({\n key: z.string().optional(),\n mode: z.enum([\"skip\", \"cancel\"]),\n })\n .optional(),\n cancel: z\n .array(\n z.strictObject({\n event: z.string(),\n if: z.string().optional(),\n timeout: z.string().optional(),\n }),\n )\n .optional(),\n debounce: z\n .strictObject({\n key: z.string().optional(),\n period: z.string().transform((x) => x as TimeStr),\n timeout: z\n .string()\n .transform((x) => x as TimeStr)\n .optional(),\n })\n .optional(),\n timeouts: z\n .strictObject({\n start: z\n .string()\n .transform((x) => x as TimeStr)\n .optional(),\n finish: z\n .string()\n .transform((x) => x as TimeStr)\n .optional(),\n })\n .optional(),\n priority: z\n .strictObject({\n run: z.string().optional(),\n })\n .optional(),\n concurrency: z\n .union([\n z.number(),\n concurrencyOptionSchema.transform((x) => x as ConcurrencyOption),\n z\n .array(concurrencyOptionSchema.transform((x) => x as ConcurrencyOption))\n .min(1)\n .max(2),\n ])\n .optional(),\n});\n\n/**\n * The shape of an individual function being synced with Inngest.\n *\n * @internal\n */\nexport type FunctionConfig = z.output<typeof functionConfigSchema>;\n\nexport interface DevServerInfo {\n /**\n * The version of the dev server.\n */\n version: string;\n authed: boolean;\n startOpts: {\n dir?: string;\n autodiscover: boolean;\n urls: string[];\n };\n functions: FunctionConfig[];\n handlers: RegisterRequest[];\n}\n\n/**\n * Given a user-friendly trigger parameter, returns the name of the event that\n * the user intends to listen to.\n *\n * @public\n */\nexport type EventNameFromTrigger<T extends InngestFunction.Trigger<string>> =\n IsNever<T> extends true // `never` indicates there are no triggers, so the payload could be anything\n ? `${internalEvents.FunctionInvoked}`\n : T extends string // `string` indicates a migration from v2 to v3\n ? T\n : // If the trigger is an event string (e.g. `{ event: \"my-event\" }`)\n T extends { event: infer IEvent } // an event trigger\n ? // If the event is an EventType (e.g. `{ event: eventType(\"my-event\") }`)\n IEvent extends EventType<infer TName, infer _TSchema>\n ? TName // Extract name from EventType\n : IEvent // Use event directly if it's a string\n : T extends { cron: string } // a cron trigger\n ? `${internalEvents.ScheduledTimer}`\n : never;\n\n/**\n * A union to represent known names of supported frameworks that we can use\n * internally to assess functionality based on a mix of framework and platform.\n */\nexport type SupportedFrameworkName =\n | \"astro\"\n | \"bun\"\n | \"cloudflare-pages\"\n | \"digitalocean\"\n | \"edge\"\n | \"express\"\n | \"aws-lambda\"\n | \"nextjs\"\n | \"nodejs\"\n | \"nuxt\"\n | \"h3\"\n | \"redwoodjs\"\n | \"remix\"\n | \"deno/fresh\"\n | \"sveltekit\"\n | \"fastify\"\n | \"koa\"\n | \"hono\"\n | \"nitro\";\n\n/**\n * A set of options that can be passed to any step to configure it.\n *\n * @public\n */\nexport interface StepOptions {\n /**\n * The ID to use to memoize the result of this step, ensuring it is run only\n * once. Changing this ID in an existing function will cause the step to be\n * run again for in-progress runs; it is recommended to use a stable ID.\n */\n id: string;\n\n /**\n * The display name to use for this step in the Inngest UI. This can be\n * changed at any time without affecting the step's behaviour.\n */\n name?: string;\n\n /**\n * The parallel execution mode for this step. Used with optimized parallelism\n * to control how steps behave in parallel execution contexts.\n *\n * - `\"race\"`: Indicates this step is part of a `Promise.race()` group. When\n * one step in the race completes, the executor can cancel remaining steps.\n *\n * Can be set directly on step options or automatically via\n * `group.parallel()`.\n */\n parallelMode?: \"race\";\n}\n\n/**\n * Either a step ID or a set of step options.\n *\n * @public\n */\nexport type StepOptionsOrId = StepOptions[\"id\"] | StepOptions;\n\n/**\n * An object containing info to target a run/step/step attempt/span, used for attaching metadata.\n */\nexport type MetadataTarget =\n | {\n // run level\n run_id: string;\n }\n | {\n // step level\n run_id: string;\n step_id: string; // user-defined\n step_index?: number;\n }\n | {\n // step attempt level\n run_id: string;\n step_id: string; // user-defined\n step_index?: number;\n step_attempt: number; // -1 === last attempt?\n }\n | {\n // span level\n run_id: string;\n step_id: string; // user-defined\n step_index?: number;\n step_attempt: number; // -1 === last attempt?\n span_id: string;\n };\n\n/**\n * A function that can be invoked by Inngest.\n */\nexport type InvokeTargetFunctionDefinition =\n | Public<InngestFunctionReference.Any>\n | Public<InngestFunction.Any>;\n\n/**\n * Given an invocation target, extract the payload that will be used to trigger\n * it.\n *\n * If we could not find a payload, will return `never`.\n */\nexport type TriggerEventFromFunction<\n TFunction extends InvokeTargetFunctionDefinition,\n> = TFunction extends InngestF