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.
330 lines • 14.6 kB
TypeScript
import { models, type AiAdapter } from "@inngest/ai";
import { z } from "zod";
import { type Jsonify } from "../helpers/jsonify.js";
import * as Temporal from "../helpers/temporal.js";
import { type ExclusiveKeys, type ParametersExceptFirst, type SendEventPayload, type SimplifyDeep, type WithoutInternalStr } from "../helpers/types.js";
import { type EventPayload, type HashedOp, type InvocationResult, type InvokeTargetFunctionDefinition, type SendEventOutput, type StepOptions, type StepOptionsOrId, type TriggerEventFromFunction, type TriggersFromClient } from "../types.js";
import { type InngestExecution } from "./execution/InngestExecution.js";
import { type ClientOptionsFromInngest, type GetEvents, type GetFunctionOutput, type Inngest } from "./Inngest.js";
export interface FoundStep extends HashedOp {
hashedId: string;
fn?: (...args: unknown[]) => unknown;
rawArgs: unknown[];
/**
* A boolean representing whether the step has been fulfilled, either
* resolving or rejecting the `Promise` returned to userland code.
*
* Note that this is distinct from {@link hasStepState}, which instead tracks
* whether the step has been given some state from the Executor. State from
* the Executor could be data other than a resolution or rejection, such as
* inputs.
*/
fulfilled: boolean;
/**
* A boolean representing whether the step has been given some state from the
* Executor. State from the Executor could be data other than a resolution or
* rejection, such as inputs.
*
* This is distinct from {@link fulfilled}, which instead tracks whether the
* step has been fulfilled, either resolving or rejecting the `Promise`
* returned to userland code.
*/
hasStepState: boolean;
handled: boolean;
/**
* The promise that has been returned to userland code for this step.
*/
promise: Promise<unknown>;
/**
* Returns a boolean representing whether or not the step was handled on this
* invocation.
*/
handle: () => boolean;
input?: unknown;
}
export type MatchOpFn<T extends (...args: unknown[]) => Promise<unknown> = (...args: unknown[]) => Promise<unknown>> = (stepOptions: StepOptions,
/**
* Arguments passed by the user.
*/
...args: ParametersExceptFirst<T>) => Omit<HashedOp, "data" | "error">;
export type StepHandler = (info: {
matchOp: MatchOpFn;
opts?: StepToolOptions;
args: [StepOptionsOrId, ...unknown[]];
}) => Promise<unknown>;
export interface StepToolOptions<T extends (...args: unknown[]) => Promise<unknown> = (...args: unknown[]) => Promise<unknown>> {
/**
* Optionally, we can also provide a function that will be called when
* Inngest tells us to run this operation.
*
* If this function is defined, the first time the tool is used it will
* report the desired operation (including options) to the Inngest. Inngest
* will then call back to the function to tell it to run the step and then
* retrieve data.
*
* We do this in order to allow functionality such as per-step retries; this
* gives the SDK the opportunity to tell Inngest what it wants to do before
* it does it.
*
* This function is passed the arguments passed by the user. It will be run
* when we receive an operation matching this one that does not contain a
* `data` property.
*/
fn?: (...args: Parameters<T>) => unknown;
}
export declare const getStepOptions: (options: StepOptionsOrId) => StepOptions;
/**
* Suffix used to namespace steps that are automatically indexed.
*/
export declare const STEP_INDEXING_SUFFIX = ":";
/**
* Create a new set of step function tools ready to be used in a step function.
* This function should be run and a fresh set of tools provided every time a
* function is run.
*
* An op stack (function state) is passed in as well as some mutable properties
* that the tools can use to submit a new op.
*/
export declare const createStepTools: <TClient extends Inngest.Any>(client: TClient, execution: InngestExecution, stepHandler: StepHandler) => {
/**
* Send one or many events to Inngest. Should always be used in place of
* `inngest.send()` to ensure that the event send is successfully retried
* and not sent multiple times due to memoisation.
*
* @example
* ```ts
* await step.sendEvent("emit-user-creation", {
* name: "app/user.created",
* data: { id: 123 },
* });
*
* await step.sendEvent("emit-user-updates", [
* {
* name: "app/user.created",
* data: { id: 123 },
* },
* {
* name: "app/user.feed.created",
* data: { id: 123 },
* },
* ]);
* ```
*
* Returns a promise that will resolve once the event has been sent.
*/
sendEvent: <Payload extends SendEventPayload<GetEvents<TClient>>>(idOrOptions: StepOptionsOrId, payload: Payload) => Promise<SendEventOutput<ClientOptionsFromInngest<TClient>>>;
/**
* Wait for a particular event to be received before continuing. When the
* event is received, it will be returned.
*
* You can also provide options to control the particular event that is
* received, for example to ensure that a user ID matches between two
* events, or to only wait a maximum amount of time before giving up and
* returning `null` instead of any event data.
*/
waitForEvent: <IncomingEvent extends WithoutInternalStr<TriggersFromClient<TClient>>>(idOrOptions: StepOptionsOrId, opts: WaitForEventOpts<GetEvents<TClient, true>, IncomingEvent>) => Promise<IncomingEvent extends WithoutInternalStr<TriggersFromClient<TClient>> ? GetEvents<TClient, false>[IncomingEvent] | null : IncomingEvent | null>;
/**
* Use this tool to run business logic. Each call to `run` will be retried
* individually, meaning you can compose complex workflows that safely
* retry dependent asynchronous actions.
*
* The function you pass to `run` will be called only when this "step" is to
* be executed and can be synchronous or asynchronous.
*
* In either case, the return value of the function will be the return value
* of the `run` tool, meaning you can return and reason about return data
* for next steps.
*/
run: <TFn extends (...args: any[]) => unknown>(idOrOptions: StepOptionsOrId, fn: TFn, ...input: Parameters<TFn>) => Promise<
/**
* TODO Middleware can affect this. If run input middleware has returned
* new step data, do not Jsonify.
*/
SimplifyDeep<Jsonify<TFn extends (...args: Parameters<TFn>) => Promise<infer U> ? Awaited<U extends void ? null : U> : ReturnType<TFn> extends void ? null : ReturnType<TFn>>>>;
/**
* AI tooling for running AI models and other AI-related tasks.
*/
ai: {
/**
* Use this tool to have Inngest make your AI calls. Useful for agentic workflows.
*
* Input is also tracked for this tool, meaning you can pass input to the
* function and it will be displayed and editable in the UI.
*/
infer: <TAdapter extends AiAdapter>(idOrOptions: StepOptionsOrId, options: AiInferOpts<TAdapter>) => Promise<AiAdapter.Output<TAdapter>>;
/**
* Use this tool to wrap AI models and other AI-related tasks. Each call
* to `wrap` will be retried individually, meaning you can compose complex
* workflows that safely retry dependent asynchronous actions.
*
* Input is also tracked for this tool, meaning you can pass input to the
* function and it will be displayed and editable in the UI.
*/
wrap: <TFn extends (...args: any[]) => unknown>(idOrOptions: StepOptionsOrId, fn: TFn, ...input: Parameters<TFn>) => Promise<
/**
* TODO Middleware can affect this. If run input middleware has returned
* new step data, do not Jsonify.
*/
SimplifyDeep<Jsonify<TFn extends (...args: Parameters<TFn>) => Promise<infer U> ? Awaited<U extends void ? null : U> : ReturnType<TFn> extends void ? null : ReturnType<TFn>>>>;
/**
* Models for AI inference and other AI-related tasks.
*/
models: {
anthropic: AiAdapter.ModelCreator<[options: models.Anthropic.AiModelOptions], models.Anthropic.AiModel>;
gemini: AiAdapter.ModelCreator<[options: models.Gemini.AiModelOptions], models.Gemini.AiModel>;
openai: AiAdapter.ModelCreator<[options: models.OpenAi.AiModelOptions], models.OpenAi.AiModel>;
deepseek: AiAdapter.ModelCreator<[options: models.DeepSeek.AiModelOptions], models.DeepSeek.AiModel>;
grok: AiAdapter.ModelCreator<[options: models.Grok.AiModelOptions], models.Grok.AiModel>;
};
};
/**
* Wait a specified amount of time before continuing.
*
* The time to wait can be specified using a `number` of milliseconds or an
* `ms`-compatible time string like `"1 hour"`, `"30 mins"`, or `"2.5d"`.
*
* {@link https://npm.im/ms}
*
* To wait until a particular date, use `sleepUntil` instead.
*/
sleep: (idOrOptions: StepOptionsOrId, time: number | string | Temporal.DurationLike) => Promise<void>;
/**
* Wait until a particular date before continuing by passing a `Date`.
*
* To wait for a particular amount of time from now, always use `sleep`
* instead.
*/
sleepUntil: (idOrOptions: StepOptionsOrId, time: Date | string | Temporal.InstantLike | Temporal.ZonedDateTimeLike) => Promise<void>;
/**
* Invoke a passed Inngest `function` with the given `data`. Returns the
* result of the returned value of the function or `null` if the function
* does not return a value.
*
* A string ID can also be passed to reference functions outside of the
* current app.
*/
invoke: <TFunction extends InvokeTargetFunctionDefinition>(idOrOptions: StepOptionsOrId, opts: InvocationOpts<TFunction>) => InvocationResult<GetFunctionOutput<TFunction>>;
};
/**
* The event payload portion of the options for `step.invoke()`. This does not
* include non-payload options like `timeout` or the function to invoke.
*/
export declare const invokePayloadSchema: z.ZodObject<{
data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
user: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
v: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
data?: Record<string, any> | undefined;
user?: Record<string, any> | undefined;
v?: string | undefined;
}, {
data?: Record<string, any> | undefined;
user?: Record<string, any> | undefined;
v?: string | undefined;
}>;
type InvocationTargetOpts<TFunction extends InvokeTargetFunctionDefinition> = {
function: TFunction;
};
type InvocationOpts<TFunction extends InvokeTargetFunctionDefinition> = InvocationTargetOpts<TFunction> & Omit<TriggerEventFromFunction<TFunction>, "id"> & {
/**
* The step function will wait for the invocation to finish for a maximum
* of this time, at which point the retured promise will be rejected
* instead of resolved with the output of the invoked function.
*
* Note that the invoked function will continue to run even if this step
* times out.
*
* The time to wait can be specified using a `number` of milliseconds, an
* `ms`-compatible time string like `"1 hour"`, `"30 mins"`, or `"2.5d"`,
* or a `Date` object.
*
* {@link https://npm.im/ms}
*/
timeout?: number | string | Date;
};
/**
* A set of optional parameters given to a `waitForEvent` call to control how
* the event is handled.
*/
type WaitForEventOpts<Events extends Record<string, EventPayload>, IncomingEvent extends keyof Events> = {
event: IncomingEvent;
/**
* The step function will wait for the event for a maximum of this time, at
* which point the event will be returned as `null` instead of any event data.
*
* The time to wait can be specified using a `number` of milliseconds, an
* `ms`-compatible time string like `"1 hour"`, `"30 mins"`, or `"2.5d"`, or
* a `Date` object.
*
* {@link https://npm.im/ms}
*/
timeout: number | string | Date;
} & ExclusiveKeys<{
/**
* If provided, the step function will wait for the incoming event to match
* particular criteria. If the event does not match, it will be ignored and
* the step function will wait for another event.
*
* It must be a string of a dot-notation field name within both events to
* compare, e.g. `"data.id"` or `"user.email"`.
*
* ```
* // Wait for an event where the `user.email` field matches
* match: "user.email"
* ```
*
* All of these are helpers for the `if` option, which allows you to specify
* a custom condition to check. This can be useful if you need to compare
* multiple fields or use a more complex condition.
*
* See the Inngest expressions docs for more information.
*
* {@link https://www.inngest.com/docs/functions/expressions}
*
* @deprecated Use `if` instead.
*/
match?: string;
/**
* If provided, the step function will wait for the incoming event to match
* the given condition. If the event does not match, it will be ignored and
* the step function will wait for another event.
*
* The condition is a string of Google's Common Expression Language. For most
* simple cases, you might prefer to use `match` instead.
*
* See the Inngest expressions docs for more information.
*
* {@link https://www.inngest.com/docs/functions/expressions}
*/
if?: string;
}, "match", "if">;
/**
* Options for `step.ai.infer()`.
*/
type AiInferOpts<TModel extends AiAdapter> = {
/**
* The model to use for the inference. Create a model by importing from
* `"inngest"` or by using `step.ai.models.*`.
*
* @example Import `openai()`
* ```ts
* import { openai } from "inngest";
*
* const model = openai({ model: "gpt-4" });
* ```
*
* @example Use a model from `step.ai.models`
* ```ts
* async ({ step }) => {
* const model = step.ai.models.openai({ model: "gpt-4" });
* }
* ```
*/
model: TModel;
/**
* The input to pass to the model.
*/
body: AiAdapter.Input<TModel>;
};
export {};
//# sourceMappingURL=InngestStepTools.d.ts.map