UNPKG

inngest

Version:

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

472 lines (470 loc) • 15.8 kB
import { MaybePromise } from "../../helpers/types.cjs"; import { Jsonify } from "../../helpers/jsonify.cjs"; import { OpenStringUnion } from "./types.cjs"; import { createStepTools } from "../InngestStepTools.cjs"; import { InngestFunction } from "../InngestFunction.cjs"; import { Context, EventPayload, JsonError, SendEventBaseOutput, StepOptions } from "../../types.cjs"; import { Inngest } from "../Inngest.cjs"; //#region src/components/middleware/middleware.d.ts /** * Namespace containing middleware-related types and base class. */ declare namespace Middleware { /** * Base interface for output transformers. Extend this and override `Out` to * create custom transformers. This is necessary because TypeScript doesn't * support higher-kinded types. * * @example * ```ts * interface BooleanToStringTransform extends Middleware.StaticTransform { * Out: this["In"] extends boolean ? string : this["In"]; * } * ``` */ export type StaticTransform = { In: unknown; Out: unknown; }; /** * Default transform. Applies the same transform as `JSON.stringify`. */ export interface DefaultStaticTransform extends StaticTransform { Out: Jsonify<this["In"]>; } /** * The step tools available to middleware for extending step functionality. * This is the same type as `step` in the function handler context. */ export type StepTools = ReturnType<typeof createStepTools<Inngest.Any>>; /** * The argument passed to `transformSendEvent`. */ export type TransformSendEventArgs = { events: EventPayload<Record<string, unknown>>[]; readonly fn: DeepReadonly<InngestFunction.Any> | null; }; /** * The argument passed to `transformStepInput`. */ export type TransformStepInputArgs = { readonly fn: DeepReadonly<InngestFunction.Any>; readonly stepInfo: Readonly<Pick<StepInfo, "hashedId" | "memoized" | "stepType">>; stepOptions: StepOptions; input: unknown[]; }; /** The argument passed to `wrapStepHandler`. */ export type WrapStepHandlerArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; next: () => Promise<unknown>; stepInfo: StepInfo; }>; /** * A single memoized step entry received in `transformFunctionInput`. */ type MemoizedStep = { type: "data"; data: unknown; } | { type: "error"; error: JsonError; } | { type: "input"; input: unknown; }; /** * Memoized step state keyed by hashed step ID. */ type MemoizedSteps = Record<string, MemoizedStep>; /** * The argument passed to `transformFunctionInput`. */ export type TransformFunctionInputArgs = { ctx: Context.Any; readonly fn: DeepReadonly<InngestFunction.Any>; steps: MemoizedSteps; }; /** * The argument passed to the static `onRegister` hook. */ export type OnRegisterArgs = Readonly<{ client: Inngest.Any; fn: InngestFunction.Any | null; }>; /** * Information about the incoming HTTP request that triggered this execution. */ export type Request = { body: () => Promise<unknown>; headers: Readonly<Record<string, string>>; method: string; url: URL; }; /** The argument passed to `wrapFunctionHandler`. */ export type WrapFunctionHandlerArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; next: () => Promise<unknown>; }>; /** The argument passed to `wrapRequest`. */ export type WrapRequestArgs = DeepReadonly<{ fn: InngestFunction.Any | null; next: () => Promise<Response>; requestArgs: readonly unknown[]; requestInfo: Request; runId: string; }>; /** The argument passed to `wrapSendEvent`. */ export type WrapSendEventArgs = DeepReadonly<{ events: EventPayload<Record<string, unknown>>[]; fn: InngestFunction.Any | null; next: () => Promise<SendEventBaseOutput>; }>; /** The argument passed to `wrapStep`. */ export type WrapStepArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; next: () => Promise<unknown>; stepInfo: StepInfo; }>; /** * The shape of the HTTP response returned by the middleware chain. * This is what `next()` resolves with inside `wrapRequest`. */ export type Response = { body: string; headers: Record<string, string>; status: number; }; /** * The argument passed to `onMemoizationEnd`. */ export type OnMemoizationEndArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; }>; /** * The argument passed to `onStepStart`. */ export type OnStepStartArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; stepInfo: StepInfo; }>; /** * The argument passed to `onStepError`. */ export type OnStepErrorArgs = DeepReadonly<{ ctx: Context.Any; error: Error; fn: InngestFunction.Any; /** * Whether this is the final attempt for the step, meaning retries are * exhausted or the error is non-retriable. When `false`, the step will be * retried. */ isFinalAttempt: boolean; stepInfo: StepInfo; }>; /** * The argument passed to `onStepComplete`. */ export type OnStepCompleteArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; output: unknown; stepInfo: StepInfo; }>; /** * The argument passed to `onRunStart`. */ export type OnRunStartArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; }>; /** * The argument passed to `onRunComplete`. */ export type OnRunCompleteArgs = DeepReadonly<{ ctx: Context.Any; fn: InngestFunction.Any; output: unknown; }>; /** * The argument passed to `onRunError`. */ export type OnRunErrorArgs = DeepReadonly<{ ctx: Context.Any; error: Error; fn: InngestFunction.Any; /** * Whether this is the final attempt for the function, meaning retries are * exhausted or the error is non-retriable. When `false`, the function will * be retried. */ isFinalAttempt: boolean; }>; /** * The type of step. This union may be extended in the future, and will not be * considered a breaking change. */ export type StepType = OpenStringUnion<"ai.infer" | "ai.wrap" | "fetch" | "group.experiment" | "invoke" | "realtime.publish" | "run" | "sendEvent" | "sleep" | "waitForEvent">; export type StepInfo = { /** * Unique ID for the step. This is a hash of the user-defined step ID, * including the implicit index if the user-defined ID is not unique. */ hashedId: string; /** * The arguments passed to the step function, if any. For `step.run()`, * these are the arguments after the id and handler function. */ input?: unknown[]; /** * Whether the step result is being retrieved from memoized state (true) * or being executed fresh (false). */ memoized: boolean; /** * Based on the first argument passed to the `step` method. */ options: StepOptions; stepType: StepType; }; /** * Base class for creating middleware. Extend this class to create custom * middleware with hooks for step execution. */ export abstract class BaseMiddleware { readonly client: Inngest.Any; /** * Used to identify the middleware instance in logs. Uniqueness is not * required, though using multiple middleware with the same ID in the same * app may cause confusion when debugging. */ abstract readonly id: string; /** * Declare this to statically specify how function return types are * transformed. By default, the function return type is Jsonified. * * Must match the same structure as `StaticTransform` to imitate * higher-kinded types. * * @example * ```ts * interface PreserveDate extends Middleware.StaticTransform { * Out: this["In"] extends Date ? Date : Jsonify<this["In"]>; * } * * class MyMiddleware extends Middleware.BaseMiddleware { * declare functionOutputTransform: PreserveDate; * } * ``` * * @default Middleware.DefaultStaticTransform (e.g. Date -> string) */ functionOutputTransform: DefaultStaticTransform; /** * Declare this to statically specify how step output types are transformed. * By default, the step output type is Jsonified. * * Must match the same structure as `StaticTransform` to imitate * higher-kinded types. * * @example * ```ts * interface PreserveDate extends Middleware.StaticTransform { * Out: this["In"] extends Date ? Date : Jsonify<this["In"]>; * } * * class MyMiddleware extends Middleware.BaseMiddleware { * declare stepOutputTransform: PreserveDate; * } * ``` * * @default Middleware.DefaultStaticTransform (e.g. Date -> string) */ stepOutputTransform: DefaultStaticTransform; constructor({ client }: { client: Inngest.Any; }); /** * Called when the middleware class is added to an Inngest client or Inngest * function. Use this for one-time setup that needs a reference to the * client instance (e.g. registering processors, setting feature flags). * * Do not mutate arguments. */ static onRegister?(args: Middleware.OnRegisterArgs): void; /** * Called 1 time per request, after memoization completes. * * If all memoized steps have been resolved/rejected, then this hook calls. * This is at the top of the function handler when there are 0 memoized * steps. * * If a new step is found before resolving/rejecting all memoized steps, * then this calls. * * Do not mutate arguments. */ onMemoizationEnd?(arg: Middleware.OnMemoizationEndArgs): MaybePromise<void>; /** * Called when the run completes successfully. Does NOT call when the run * errors: `onRunError` calls instead. * * Do not mutate arguments. */ onRunComplete?(arg: Middleware.OnRunCompleteArgs): MaybePromise<void>; /** * Called when the function throws an error. * * Do not mutate arguments. */ onRunError?(arg: Middleware.OnRunErrorArgs): MaybePromise<void>; /** * Called 1 time per run on the very first request (0 memoized steps, * attempt 0). Does NOT call on subsequent requests where steps are being * replayed. * * Do not mutate arguments. */ onRunStart?(arg: Middleware.OnRunStartArgs): MaybePromise<void>; /** * Called when a step successfully completes. Only called for `step.run` * and `step.sendEvent`. Never called for memoized step outputs. Does NOT * call when the step errors: `onStepError` calls instead. * * Do not mutate arguments. */ onStepComplete?(arg: Middleware.OnStepCompleteArgs): MaybePromise<void>; /** * Called each time a step errors. Only called for `step.run` and * `step.sendEvent`. Never called for memoized errors. * * Do not mutate arguments. */ onStepError?(arg: Middleware.OnStepErrorArgs): MaybePromise<void>; /** * Called 1 time per step before running its handler. Only called for * `step.run` and `step.sendEvent`. * * Do not mutate arguments. */ onStepStart?(arg: Middleware.OnStepStartArgs): MaybePromise<void>; /** * Called 1 time per request (likely multiple times per run). Return the * (potentially modified) arg object. * * Use cases: * - Dependency injection. * - Deserialize events before passing it to the function handler. * * Do not mutate arguments. */ transformFunctionInput?(arg: Middleware.TransformFunctionInputArgs): MaybePromise<Middleware.TransformFunctionInputArgs>; /** * Called when sending events. This is either `step.sendEvent` or * `client.send`. Return the (potentially modified) arg object. * * Use cases: * - Serialize event data before sending it to the Inngest Server. * * Do not mutate arguments. */ transformSendEvent?(arg: Middleware.TransformSendEventArgs): MaybePromise<Middleware.TransformSendEventArgs>; /** * Called 1 time per step per request (likely multiple times per step). * Return the (potentially modified) arg object. * * Use cases: * - Modify step options (e.g. the step ID). * - Modify step input args. * * Do not mutate arguments. */ transformStepInput?(arg: TransformStepInputArgs): MaybePromise<TransformStepInputArgs>; /** * Called 1 time per request. * * Use cases: * - AsyncLocalStorage context. * - Function-level output/error transformation. * - Prepend/append steps around the function handler. * * Must call `next()` to continue processing. Do not mutate arguments. * * **Important:** `next()` only resolves when the function completes. On * requests where a fresh step is discovered, control flow is interrupted * and `next()` never resolves. */ wrapFunctionHandler?(args: WrapFunctionHandlerArgs): Promise<unknown>; /** * Called 1 time per request. * * Use cases: * - Custom auth. * - Expose request data to the Inngest function handler. * - Metrics. * * Must call `next()` to continue processing. Do not mutate arguments. */ wrapRequest?(args: WrapRequestArgs): Promise<Response>; /** * Called each time events are sent (either `client.send` or * `step.sendEvent`). * * Use cases: * - Backup events (e.g. blob store) when they fail to send. * - Metrics. * * Must call `next()` to continue processing. Do not mutate arguments. */ wrapSendEvent?(args: WrapSendEventArgs): Promise<SendEventBaseOutput>; /** * Called 1 time per step per request. Called for all step kinds. Depending * on your use case, you may want `wrapStepHandler` instead. * * Use cases: * - Deserialize step output before returning it to the function handler. * - Handle step failure errors (after exhausting retries). * - Prepend/append steps around a step. * * Must call `next()` to continue processing. Do not mutate arguments. * * NOTE: `next()` only resolves when the step completes/fails. On requests * where a fresh step is discovered, control flow is interrupted and * `next()` never resolves. */ wrapStep?(args: WrapStepArgs): Promise<unknown>; /** * Called 1 time per step attempt. Wraps the step's handler. Only called for * `step.run` and `step.sendEvent`. Use this to modify the handler's * returned output or thrown error before it's sent to the Inngest Server. * * Use cases: * - Serialize step output before sending it to the Inngest Server. * - Handle step attempt errors (before exhausting retries). * * Must call `next()` to continue processing. Do not mutate arguments. */ wrapStepHandler?(args: WrapStepHandlerArgs): Promise<unknown>; } /** * A no-arg constructor for a BaseMiddleware subclass. Used in client and * function options so that fresh instances are created per-request. */ export type Class = (new (args: { client: Inngest.Any; }) => BaseMiddleware) & { onRegister?(arg: OnRegisterArgs): void; }; export {}; } type DeepReadonly<T> = T extends (infer U)[] ? readonly DeepReadonly<U>[] : T extends Function ? T : T extends Date | RegExp | Error | Map<unknown, unknown> | Set<unknown> ? Readonly<T> : T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]> } : T; //#endregion export { Middleware }; //# sourceMappingURL=middleware.d.cts.map