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.

620 lines (619 loc) • 25.7 kB
import { AsArray, IsNever, MaybePromise, SendEventPayload, SimplifyDeep, SingleOrArray } from "../helpers/types.cjs"; import { Logger, ProxyLogger } from "../middleware/logger.cjs"; import { Jsonify } from "../helpers/jsonify.cjs"; import { Middleware } from "./middleware/middleware.cjs"; import { Realtime } from "./realtime/types.cjs"; import { createStepTools } from "./InngestStepTools.cjs"; import { MetadataBuilder } from "./InngestMetadata.cjs"; import { InngestFunction } from "./InngestFunction.cjs"; import { InngestFunctionReference } from "./InngestFunctionReference.cjs"; import { ApplyAllMiddlewareCtxExtensions, ApplyAllMiddlewareStepExtensions, ApplyAllMiddlewareTransforms, BaseContext, ClientOptions, EventPayload, FailureEventArgs, Handler, InvokeTargetFunctionDefinition, JsonError, SendEventBaseOutput, SendEventOutput, TimeStr, TimeStrBatch } from "../types.cjs"; import { InngestApi } from "../api/api.cjs"; import { HandlerWithTriggers } from "./triggers/typeHelpers.cjs"; import { Mode } from "../helpers/env.cjs"; //#region src/components/Inngest.d.ts type ChannelTopicNames<InputChannel extends Realtime.ChannelInput> = Extract<keyof Realtime.Channel.InferTopics<InputChannel>, string>; type ChannelTopicsInput<InputChannel extends Realtime.ChannelInput> = [ChannelTopicNames<InputChannel>] extends [never] ? string[] : string extends ChannelTopicNames<InputChannel> ? string[] : ChannelTopicNames<InputChannel>[]; /** * Capturing the global type of fetch so that we can reliably access it below. */ type FetchT = typeof fetch; /** * A client used to interact with the Inngest API by sending or reacting to * events. * * ```ts * const inngest = new Inngest({ id: "my-app" }); * ``` * * @public */ /** * Symbol for accessing the SDK's internal logger. Not part of the public API. * @internal */ declare const internalLoggerSymbol: unique symbol; declare class Inngest<const TClientOpts extends ClientOptions = ClientOptions> implements Inngest.Like { get [Symbol.toStringTag](): typeof Inngest.Tag; /** * The ID of this instance, most commonly a reference to the application it * resides in. * * The ID of your client should remain the same for its lifetime; if you'd * like to change the name of your client as it appears in the Inngest UI, * change the `name` property instead. */ readonly id: string; /** * Stores the options so we can remember explicit settings the user has * provided. */ private readonly options; private readonly inngestApi; private readonly _userProvidedFetch?; private _cachedFetch?; private readonly _logger; /** * Logger for SDK internal messages. Falls back to the user's `logger` if * `internalLogger` is not provided in client options. * * @internal */ readonly [internalLoggerSymbol]: Logger; private localFns; /** * Middleware instances that provide simpler hooks. */ readonly middleware: Middleware.Class[]; private _env; private _appVersion; /** * @internal * Flag set by metadataMiddleware to enable step.metadata() */ protected experimentalMetadataEnabled: boolean; /** * A dummy Inngest function used in Durable Endpoints. This is necessary * because the vast majority of middleware hooks require the Inngest function. * But for Durable Endpoints, there is no Inngest function. So we need some * placeholder. */ private dummyDurableEndpointFunction; private getDummyDurableEndpointFunction; /** * Try to parse the `INNGEST_DEV` environment variable as a URL. * Returns the URL if valid, otherwise `undefined`. */ get explicitDevUrl(): URL | undefined; /** * Given a default cloud URL, return the appropriate URL based on the * current mode and environment variables. * * If `INNGEST_DEV` is set to a URL, that URL is used. Otherwise, we use * the default cloud URL in cloud mode or the default dev server host in * dev mode. */ private resolveDefaultUrl; get apiBaseUrl(): string; get eventBaseUrl(): string; get eventKey(): string | undefined; get fetch(): FetchT; get signingKey(): string | undefined; get signingKeyFallback(): string | undefined; get headers(): Record<string, string>; /** * The base logger for this client. Passed to user functions as `ctx.logger`. */ get logger(): Logger; get env(): string | null; get appVersion(): string | undefined; /** * Access the metadata builder for updating run and step metadata. * * @example * ```ts * // Update metadata for the current run * await inngest.metadata.update({ status: "processing" }); * * // Update metadata for a different run * await inngest.metadata.run(otherRunId).update({ key: "val" }); * * ``` */ get metadata(): MetadataBuilder; /** * A client used to interact with the Inngest API by sending or reacting to * events. * * ```ts * const inngest = new Inngest({ id: "my-app" }); * ``` */ constructor(options: TClientOpts); /** * Returns a `Promise` that resolves when the app is ready and all middleware * has been initialized. */ get ready(): Promise<void>; /** * Set the environment variables for this client. This is useful if you are * passed environment variables at runtime instead of as globals and need to * update the client with those values as requests come in. */ setEnvVars(env?: Record<string, string | undefined>): this; get mode(): Mode; /** * Given a response from Inngest, relay the error to the caller. */ private getResponseError; private eventKeySet; /** * EXPERIMENTAL: This API is not yet stable and may change in the future * without a major version bump. * * Send a Signal to Inngest. */ sendSignal({ signal, data, env }: { /** * The signal to send. */ signal: string; /** * The data to send with the signal. */ data?: unknown; /** * The Inngest environment to send the signal to. Defaults to whichever * environment this client's key is associated with. * * It's like you never need to change this unless you're trying to sync * multiple systems together using branch names. */ env?: string; }): Promise<InngestApi.SendSignalResponse>; private _sendSignal; private updateMetadata; private warnMetadata; /** * Realtime-related functionality for this Inngest client. */ realtime: { /** * Publish data to a realtime channel topic. * * This is a non-durable publish, it executes immediately and is not * memoized. If called inside an Inngest function, it will automatically * include the current run ID. For durable publishing inside functions, use * `step.realtime.publish()`. * * ```ts * await inngest.realtime.publish(ch.status, { message: "Processing..." }); * ``` */ publish: Realtime.TypedPublishFn; /** * Subscribe to realtime messages on a channel, returning a readable stream. */ subscribe: { <const InputChannel extends Realtime.ChannelInput, const InputTopics extends ChannelTopicsInput<InputChannel>, const TToken extends Realtime.Subscribe.Token<InputChannel, InputTopics>>(opts: { channel: InputChannel; topics: InputTopics; validate?: boolean; onMessage: Realtime.Subscribe.Callback<TToken>; onError?: (err: unknown) => void; }): Promise<Realtime.Subscribe.CallbackSubscription>; <const InputChannel extends Realtime.ChannelInput, const InputTopics extends ChannelTopicsInput<InputChannel>, const TToken extends Realtime.Subscribe.Token<InputChannel, InputTopics>>(opts: { channel: InputChannel; topics: InputTopics; validate?: boolean; }): Promise<Realtime.Subscribe.StreamSubscription<TToken>>; }; /** * Generate a subscription token for subscribing to realtime messages. */ token: <const InputChannel extends Realtime.ChannelInput, const InputTopics extends ChannelTopicsInput<InputChannel>, const TToken extends Realtime.Subscribe.Token<InputChannel, InputTopics>>(opts: { channel: InputChannel; topics: InputTopics; }) => Promise<TToken>; }; endpoint<THandler extends Inngest.EndpointHandler<this>>(handler: THandler): THandler; /** * Creates a proxy handler that polls Inngest for durable endpoint results. * * The proxy: * - Extracts `runId` and `token` from query params * - Fetches the result from Inngest API * - Runs the response through middleware (e.g., decryption) * - Adds CORS headers * * Use this in combination with the `asyncRedirectUrl` option on your * endpoint adapter to redirect users to your own proxy endpoint instead * of directly to Inngest. * * @example * ```ts * import { Inngest } from "inngest"; * import { endpointAdapter } from "inngest/edge"; * * const inngest = new Inngest({ * id: "my-app", * endpointAdapter: endpointAdapter.withOptions({ * asyncRedirectUrl: "/api/inngest/poll", * }), * }); * * // Durable endpoint * export const GET = inngest.endpoint(async (req) => { * const result = await step.run("work", () => "done"); * return new Response(result); * }); * * // Proxy endpoint at /api/inngest/poll * export const GET = inngest.endpointProxy(); * ``` */ endpointProxy(): Inngest.ProxyHandler<this>; /** * Decrypt a proxy response using the client's middleware stack. * * Runs `transformFunctionInput` on each middleware instance to decrypt * step data (used by encryption middleware). * * Uses type assertions because we're creating a minimal "fake" execution * context just to run the decryption middleware hooks - not a full execution. * * @internal */ private decryptProxyResult; /** * Send one or many events to Inngest. Takes an entire payload (including * name) as each input. * * ```ts * await inngest.send({ name: "app/user.created", data: { id: 123 } }); * ``` * * Returns a promise that will resolve if the event(s) were sent successfully, * else throws with an error explaining what went wrong. */ send(payload: SendEventPayload, options?: { /** * The Inngest environment to send events to. Defaults to whichever * environment this client's event key is associated with. * * It's likely you never need to change this unless you're trying to sync * multiple systems together using branch names. */ env?: string; }): Promise<SendEventOutput<TClientOpts>>; /** * Internal method for sending an event, used to allow Inngest internals to * further customize the request sent to an Inngest Server. */ private _send; createFunction: Inngest.CreateFunction<this>; get funcs(): InngestFunction.Any[]; private _createFunction; /** * Runtime-only validation. */ private sanitizeTriggers; } /** * Default middleware that is included in every client, placed before the user's * middleware. Returns new-style `Middleware.Class` constructors. Uses a closure * so the no-arg constructors can capture the base logger. */ declare function builtInMiddleware(baseLogger: Logger): readonly [{ new ({ client }: { client: Inngest.Any; }): { readonly id: "inngest:logger"; proxyLogger: ProxyLogger; transformFunctionInput(arg: Middleware.TransformFunctionInputArgs): { ctx: Omit<BaseContext<Inngest.Any>, never> & Record<never, never> & { logger: Logger; }; fn: { readonly opts: { readonly triggers?: any; readonly id: string; readonly name?: string | undefined; readonly description?: string | undefined; readonly concurrency?: number | { readonly limit: number; readonly key?: string | undefined; readonly scope?: "fn" | "env" | "account" | undefined; } | readonly { readonly limit: number; readonly key?: string | undefined; readonly scope?: "fn" | "env" | "account" | undefined; }[] | undefined; readonly batchEvents?: { readonly maxSize: number; readonly timeout: TimeStrBatch; readonly key?: string | undefined; readonly if?: string | undefined; } | undefined; readonly idempotency?: string | undefined; readonly rateLimit?: { readonly key?: string | undefined; readonly limit: number; readonly period: TimeStr; } | undefined; readonly throttle?: { readonly key?: string | undefined; readonly limit: number; readonly period: TimeStr; readonly burst?: number | undefined; } | undefined; readonly debounce?: { readonly key?: string | undefined; readonly period: TimeStr; readonly timeout?: TimeStr | undefined; } | undefined; readonly priority?: { readonly run?: string | undefined; } | undefined; readonly timeouts?: { readonly start?: TimeStr | undefined; readonly finish?: TimeStr | undefined; } | undefined; readonly singleton?: { readonly key?: string | undefined; readonly mode: "skip" | "cancel"; } | undefined; readonly cancelOn?: readonly { readonly event: string | { readonly event: string; readonly name: string; readonly schema: any; readonly version?: string | undefined; readonly create: (...args: [data?: Record<string, unknown> | undefined, options?: { id?: string; ts?: number; v?: string; } | undefined] | [data: unknown, options?: { id?: string; ts?: number; v?: string; } | undefined]) => { data: unknown; name: string; id?: string; ts?: number; v?: string; } & { validate: () => Promise<void>; }; }; readonly if?: string | undefined; readonly match?: string | undefined; readonly timeout?: string | number | Readonly<Date> | undefined; }[] | undefined; readonly retries?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | undefined; readonly onFailure?: any; readonly middleware?: readonly Middleware.Class[] | undefined; readonly optimizeParallelism?: boolean | undefined; readonly experimentalCheckpointing?: boolean | { readonly maxRuntime?: string | number | { readonly [Symbol.toStringTag]: "Temporal.Duration"; } | undefined; readonly bufferedSteps?: number | undefined; readonly maxInterval?: string | number | { readonly [Symbol.toStringTag]: "Temporal.Duration"; } | undefined; } | undefined; readonly checkpointing?: boolean | { readonly maxRuntime?: string | number | { readonly [Symbol.toStringTag]: "Temporal.Duration"; } | undefined; readonly bufferedSteps?: number | undefined; readonly maxInterval?: string | number | { readonly [Symbol.toStringTag]: "Temporal.Duration"; } | undefined; } | undefined; }; readonly id: (prefix?: string) => string; readonly name: string; readonly description: string | undefined; readonly [Symbol.toStringTag]: typeof InngestFunction.Tag; }; steps: { [x: string]: { type: "data"; data: unknown; } | { type: "error"; error: JsonError; } | { type: "input"; input: unknown; }; }; }; onMemoizationEnd(): void; onStepError(arg: Middleware.OnStepErrorArgs): void; wrapFunctionHandler({ next }: Middleware.WrapFunctionHandlerArgs): Promise<unknown>; wrapRequest({ next }: Middleware.WrapRequestArgs): Promise<Middleware.Response>; readonly client: Inngest.Any; functionOutputTransform: Middleware.DefaultStaticTransform; stepOutputTransform: Middleware.DefaultStaticTransform; onRunComplete?(arg: Middleware.OnRunCompleteArgs): MaybePromise<void>; onRunError?(arg: Middleware.OnRunErrorArgs): MaybePromise<void>; onRunStart?(arg: Middleware.OnRunStartArgs): MaybePromise<void>; onStepComplete?(arg: Middleware.OnStepCompleteArgs): MaybePromise<void>; onStepStart?(arg: Middleware.OnStepStartArgs): MaybePromise<void>; transformSendEvent?(arg: Middleware.TransformSendEventArgs): MaybePromise<Middleware.TransformSendEventArgs>; transformStepInput?(arg: Middleware.TransformStepInputArgs): MaybePromise<Middleware.TransformStepInputArgs>; wrapSendEvent?(args: Middleware.WrapSendEventArgs): Promise<SendEventBaseOutput>; wrapStep?(args: Middleware.WrapStepArgs): Promise<unknown>; wrapStepHandler?(args: Middleware.WrapStepHandlerArgs): Promise<unknown>; }; onRegister?(args: Middleware.OnRegisterArgs): void; }]; /** * A client used to interact with the Inngest API by sending or reacting to * events. * * ```ts * const inngest = new Inngest({ id: "my-app" }); * ``` * * @public */ declare namespace Inngest { export const Tag: "Inngest.App"; /** * Represents any `Inngest` instance, regardless of generics and inference. * * Prefer use of `Inngest.Like` where possible to ensure compatibility with * multiple versions. */ export type Any = Inngest; /** * References any `Inngest` instance across library versions, useful for use * in public APIs to ensure compatibility with multiple versions. * * Prefer use of `Inngest.Any` internally and `Inngest.Like` for public APIs. */ export interface Like { readonly [Symbol.toStringTag]: typeof Inngest.Tag; } export type EndpointHandler<TClient extends Inngest.Any> = ReturnType<NonNullable<ClientOptionsFromInngest<TClient>["endpointAdapter"]>>; type ResolveTriggers<T> = T extends undefined ? [] : AsArray<NonNullable<T>>; /** * Input type for createFunction that accepts raw trigger input (single, array, or undefined) * while keeping all other fields from InngestFunction.Options. */ export type CreateFunctionInput<TFnMiddleware extends Middleware.Class[] | undefined, TTriggers extends SingleOrArray<InngestFunction.Trigger<string>> | undefined, TFailureHandler extends Handler.Any> = Omit<InngestFunction.Options<InngestFunction.Trigger<string>[], TFailureHandler>, "triggers"> & { triggers?: TTriggers; middleware?: TFnMiddleware; }; /** * The type of the proxy handler returned by `endpointProxy()`. * * This type is inferred from the `createProxyHandler` function of the * endpoint adapter configured on the client. */ export type ProxyHandler<TClient extends Inngest.Any> = ReturnType<NonNullable<NonNullable<ClientOptionsFromInngest<TClient>["endpointAdapter"]>["createProxyHandler"]>>; export type CreateFunction<TClient extends Inngest.Any> = <const TTriggers extends SingleOrArray<InngestFunction.Trigger<string>> | undefined = undefined, const TFnMiddleware extends Middleware.Class[] | undefined = undefined, THandler extends Handler.Any = HandlerWithTriggers<ReturnType<typeof createStepTools<TClient, TFnMiddleware>>, ResolveTriggers<TTriggers>, ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> & ApplyAllMiddlewareCtxExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & { step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> & ApplyAllMiddlewareStepExtensions<ClientOptionsFromInngest<TClient>["middleware"]>; }>, TFailureHandler extends Handler.Any = HandlerWithTriggers<ReturnType<typeof createStepTools<TClient, TFnMiddleware>>, ResolveTriggers<TTriggers>, ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> & FailureEventArgs<EventPayload> & ApplyAllMiddlewareCtxExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & { step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> & ApplyAllMiddlewareStepExtensions<ClientOptionsFromInngest<TClient>["middleware"]>; }>>(options: CreateFunctionInput<TFnMiddleware, TTriggers, TFailureHandler>, handler: THandler) => InngestFunction<InngestFunction.Options<ResolveTriggers<TTriggers>, TFailureHandler>, THandler, TFailureHandler, TClient, ResolveTriggers<TTriggers>>; export {}; } /** * A helper type to extract the type of a set of event tooling from a given * Inngest instance and optionally a trigger. * * @example Get generic step tools for an Inngest instance. * ```ts * type StepTools = GetStepTools<typeof inngest>; * ``` * * @example Get step tools with a trigger, ensuring tools like `waitForEvent` are typed. * ```ts * type StepTools = GetStepTools<typeof Inngest, "github/pull_request">; * ``` * * @public */ type GetStepTools<TInngest extends Inngest.Any> = GetFunctionInput<TInngest> extends { step: infer TStep; } ? TStep : never; /** * A helper type to extract the type of the input to a function from a given * Inngest instance and optionally a trigger. * * @example Get generic function input for an Inngest instance. * ```ts * type Input = GetFunctionInput<typeof inngest>; * ``` * * @example Get function input with a trigger, ensuring tools like `waitForEvent` are typed. * ```ts * type Input = GetFunctionInput<typeof Inngest, "github/pull_request">; * ``` * * @public */ type GetFunctionInput<TClient extends Inngest.Any> = Parameters<Handler<TClient, ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> & ApplyAllMiddlewareCtxExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & { step: ReturnType<typeof createStepTools<TClient>> & ApplyAllMiddlewareStepExtensions<ClientOptionsFromInngest<TClient>["middleware"]>; }>>[0]; /** * A helper type to extract the type of the output of an Inngest function. * * @example Get a function's output * ```ts * type Output = GetFunctionOutput<typeof myFunction>; * ``` * * @public */ type GetFunctionOutput<TFunction extends InvokeTargetFunctionDefinition> = TFunction extends InngestFunction.Any ? GetFunctionOutputFromInngestFunction<TFunction> : TFunction extends InngestFunctionReference.Any ? GetFunctionOutputFromReferenceInngestFunction<TFunction> : unknown; /** * A helper type to extract the type of the output of an Inngest function. * * Used internally for {@link GetFunctionOutput}. Code outside of this package * should use {@link GetFunctionOutput} instead. * * @internal */ type GetFunctionOutputFromInngestFunction<TFunction extends InngestFunction.Any> = TFunction extends InngestFunction<any, infer IHandler, any, infer TClient, any> ? IsNever<VoidToNull<SimplifyDeep<Awaited<ReturnType<IHandler>>>>> extends true ? null : ApplyAllMiddlewareTransforms<ClientOptionsFromInngest<TClient>["middleware"], VoidToNull<SimplifyDeep<Awaited<ReturnType<IHandler>>>>, "functionOutputTransform"> : unknown; /** * A helper type to extract the type of the output of a referenced Inngest * function. * * Used internally for {@link GetFunctionOutput}. Code outside of this package * should use {@link GetFunctionOutput} instead. * * @internal */ type GetFunctionOutputFromReferenceInngestFunction<TFunction extends InngestFunctionReference.Any> = TFunction extends InngestFunctionReference<any, infer IOutput> ? IsNever<SimplifyDeep<Jsonify<IOutput>>> extends true ? null : SimplifyDeep<Jsonify<IOutput>> : unknown; /** * A helper type to extract the raw (non-Jsonified) output type of an Inngest * function. This is used when middleware transforms will handle serialization. * * @internal */ type GetFunctionOutputRaw<TFunction extends InvokeTargetFunctionDefinition> = TFunction extends InngestFunction.Any ? GetFunctionOutputRawFromInngestFunction<TFunction> : TFunction extends InngestFunctionReference.Any ? GetFunctionOutputRawFromReferenceInngestFunction<TFunction> : unknown; /** * @internal */ type GetFunctionOutputRawFromInngestFunction<TFunction extends InngestFunction.Any> = TFunction extends InngestFunction<any, infer IHandler, any, any, any> ? VoidToNull<Awaited<ReturnType<IHandler>>> : unknown; /** * @internal */ type GetFunctionOutputRawFromReferenceInngestFunction<TFunction extends InngestFunctionReference.Any> = TFunction extends InngestFunctionReference<any, infer IOutput> ? VoidToNull<SimplifyDeep<IOutput>> : unknown; /** * Helper type that converts void/undefined/never to null. * Uses ReturnType trick to check for void without directly using void in type position. * @internal */ type VoidToNull<T> = IsNever<T> extends true ? null : T extends ReturnType<() => void> ? null : T; /** * A helper type to extract the inferred options from a given Inngest instance. * * @example * ```ts * type Options = ClientOptionsFromInngest<typeof inngest>; * ``` * * @public */ type ClientOptionsFromInngest<TInngest extends Inngest.Any> = TInngest extends Inngest<infer U> ? U : ClientOptions; //#endregion export { ClientOptionsFromInngest, GetFunctionInput, GetFunctionOutput, GetFunctionOutputRaw, GetStepTools, Inngest }; //# sourceMappingURL=Inngest.d.cts.map