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.

1 lines • 50.9 kB
{"version":3,"file":"Inngest.cjs","names":["InngestFunction","envKeys","parseAsBoolean","normalizeUrl","defaultDevServerHost","defaultInngestApiBaseUrl","defaultInngestEventBaseUrl","getFetch","inngestHeaders","headerKeys","UnscopedMetadataBuilder","allProcessEnv","InngestApi","ConsoleLogger","headers: Record<string, string>","fields: Record<string, unknown>","formatLogMessage","getAsyncCtx","realtimeSubscribe","realtimeGetSubscriptionToken","transformArgs: Middleware.TransformFunctionInputArgs","createEntropy","payloads: EventPayload[]","payload","isValidatable","fixEventKeyMissingSteps","retryWithBackoff","rawBody: unknown","body: SendEventResponse | undefined","dummyEventKey","stringify","sendEventResponseSchema","buildWrapSendEventChain","Middleware","ProxyLogger","logger: Logger"],"sources":["../../src/components/Inngest.ts"],"sourcesContent":["import { InngestApi } from \"../api/api.ts\";\nimport {\n defaultDevServerHost,\n defaultInngestApiBaseUrl,\n defaultInngestEventBaseUrl,\n dummyEventKey,\n envKeys,\n headerKeys,\n} from \"../helpers/consts.ts\";\nimport { createEntropy } from \"../helpers/crypto.ts\";\nimport {\n allProcessEnv,\n type Env,\n getFetch,\n inngestHeaders,\n type Mode,\n normalizeUrl,\n parseAsBoolean,\n} from \"../helpers/env.ts\";\nimport { type ErrCode, fixEventKeyMissingSteps } from \"../helpers/errors.ts\";\nimport type { Jsonify } from \"../helpers/jsonify.ts\";\nimport { formatLogMessage, type StructuredLogMessage } from \"../helpers/log.ts\";\nimport { retryWithBackoff } from \"../helpers/promises.ts\";\nimport { stringify } from \"../helpers/strings.ts\";\nimport type {\n AsArray,\n IsNever,\n SendEventPayload,\n SimplifyDeep,\n SingleOrArray,\n} from \"../helpers/types.ts\";\nimport {\n ConsoleLogger,\n type Logger,\n ProxyLogger,\n} from \"../middleware/logger.ts\";\nimport {\n type ApplyAllMiddlewareCtxExtensions,\n type ApplyAllMiddlewareStepExtensions,\n type ApplyAllMiddlewareTransforms,\n type BaseContext,\n type ClientOptions,\n type EventPayload,\n type FailureEventArgs,\n type Handler,\n type InvokeTargetFunctionDefinition,\n type MetadataTarget,\n type SendEventOutput,\n type SendEventResponse,\n sendEventResponseSchema,\n} from \"../types.ts\";\n\nimport { getAsyncCtx } from \"./execution/als.ts\";\nimport { InngestFunction } from \"./InngestFunction.ts\";\nimport type { InngestFunctionReference } from \"./InngestFunctionReference.ts\";\nimport {\n type MetadataBuilder,\n UnscopedMetadataBuilder,\n} from \"./InngestMetadata.ts\";\nimport type { createStepTools } from \"./InngestStepTools.ts\";\nimport { step } from \"./InngestStepTools.ts\";\nimport { buildWrapSendEventChain, Middleware } from \"./middleware/index.ts\";\nimport {\n getSubscriptionToken as realtimeGetSubscriptionToken,\n subscribe as realtimeSubscribe,\n} from \"./realtime/subscribe/index.ts\";\nimport type { Realtime } from \"./realtime/types\";\nimport {\n type HandlerWithTriggers,\n isValidatable,\n} from \"./triggers/typeHelpers.ts\";\n\ntype ChannelTopicNames<InputChannel extends Realtime.ChannelInput> = Extract<\n keyof Realtime.Channel.InferTopics<InputChannel>,\n string\n>;\n\ntype ChannelTopicsInput<InputChannel extends Realtime.ChannelInput> = [\n ChannelTopicNames<InputChannel>,\n] extends [never]\n ? string[]\n : string extends ChannelTopicNames<InputChannel>\n ? string[]\n : ChannelTopicNames<InputChannel>[];\n\n/**\n * Capturing the global type of fetch so that we can reliably access it below.\n */\ntype FetchT = typeof fetch;\n\n/**\n * A client used to interact with the Inngest API by sending or reacting to\n * events.\n *\n * ```ts\n * const inngest = new Inngest({ id: \"my-app\" });\n * ```\n *\n * @public\n */\n\n/**\n * Symbol for accessing the SDK's internal logger. Not part of the public API.\n * @internal\n */\nexport const internalLoggerSymbol = Symbol.for(\"inngest.internalLogger\");\n\nexport class Inngest<const TClientOpts extends ClientOptions = ClientOptions>\n implements Inngest.Like\n{\n get [Symbol.toStringTag](): typeof Inngest.Tag {\n return Inngest.Tag;\n }\n\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 public readonly id: string;\n\n /**\n * Stores the options so we can remember explicit settings the user has\n * provided.\n */\n private readonly options: TClientOpts;\n\n private readonly inngestApi: InngestApi;\n\n private readonly _userProvidedFetch?: FetchT;\n private _cachedFetch?: FetchT;\n\n private readonly _logger: Logger;\n\n /**\n * Logger for SDK internal messages. Falls back to the user's `logger` if\n * `internalLogger` is not provided in client options.\n *\n * @internal\n */\n readonly [internalLoggerSymbol]: Logger;\n\n private localFns: InngestFunction.Any[] = [];\n\n /**\n * Middleware instances that provide simpler hooks.\n */\n readonly middleware: Middleware.Class[];\n\n private _env: Env = {};\n\n private _appVersion: string | undefined;\n\n /**\n * @internal\n * Flag set by metadataMiddleware to enable step.metadata()\n */\n protected experimentalMetadataEnabled = false;\n\n /**\n * A dummy Inngest function used in Durable Endpoints. This is necessary\n * because the vast majority of middleware hooks require the Inngest function.\n * But for Durable Endpoints, there is no Inngest function. So we need some\n * placeholder.\n */\n private dummyDurableEndpointFunction: InngestFunction.Any | null = null;\n private getDummyDurableEndpointFunction(): InngestFunction.Any {\n if (this.dummyDurableEndpointFunction) {\n return this.dummyDurableEndpointFunction;\n }\n this.dummyDurableEndpointFunction = new InngestFunction(\n this,\n { id: \"__proxy__\", triggers: [] },\n async () => {},\n );\n return this.dummyDurableEndpointFunction;\n }\n\n /**\n * Try to parse the `INNGEST_DEV` environment variable as a URL.\n * Returns the URL if valid, otherwise `undefined`.\n */\n get explicitDevUrl(): URL | undefined {\n const devEnvValue = this._env[envKeys.InngestDevMode];\n if (typeof devEnvValue !== \"string\" || !devEnvValue) {\n return undefined;\n }\n\n if (parseAsBoolean(devEnvValue) !== undefined) {\n return undefined;\n }\n\n try {\n return new URL(normalizeUrl(devEnvValue));\n } catch {\n return undefined;\n }\n }\n\n /**\n * Given a default cloud URL, return the appropriate URL based on the\n * current mode and environment variables.\n *\n * If `INNGEST_DEV` is set to a URL, that URL is used. Otherwise, we use\n * the default cloud URL in cloud mode or the default dev server host in\n * dev mode.\n */\n private resolveDefaultUrl(cloudUrl: string): string {\n const explicitDevUrl = this.explicitDevUrl;\n if (explicitDevUrl) {\n return explicitDevUrl.href;\n }\n\n return this.mode === \"cloud\" ? cloudUrl : defaultDevServerHost;\n }\n\n get apiBaseUrl(): string {\n return (\n this.options.baseUrl ||\n this._env[envKeys.InngestApiBaseUrl] ||\n this._env[envKeys.InngestBaseUrl] ||\n this.resolveDefaultUrl(defaultInngestApiBaseUrl)\n );\n }\n\n get eventBaseUrl(): string {\n return (\n this.options.baseUrl ||\n this._env[envKeys.InngestEventApiBaseUrl] ||\n this._env[envKeys.InngestBaseUrl] ||\n this.resolveDefaultUrl(defaultInngestEventBaseUrl)\n );\n }\n\n get eventKey(): string | undefined {\n return (\n this.options.eventKey || this._env[envKeys.InngestEventKey] || undefined\n );\n }\n\n // defer fetch resolution until first use, but cache for reference stability\n get fetch(): FetchT {\n if (!this._cachedFetch) {\n this._cachedFetch = this._userProvidedFetch\n ? getFetch(this[internalLoggerSymbol], this._userProvidedFetch)\n : getFetch(this[internalLoggerSymbol], globalThis.fetch);\n }\n return this._cachedFetch;\n }\n\n get signingKey(): string | undefined {\n return this.options.signingKey || this._env[envKeys.InngestSigningKey];\n }\n\n get signingKeyFallback(): string | undefined {\n return (\n this.options.signingKeyFallback ||\n this._env[envKeys.InngestSigningKeyFallback]\n );\n }\n\n get headers(): Record<string, string> {\n return inngestHeaders({\n inngestEnv: this.options.env,\n env: this._env,\n });\n }\n\n /**\n * The base logger for this client. Passed to user functions as `ctx.logger`.\n */\n get logger(): Logger {\n return this._logger;\n }\n\n get env(): string | null {\n return this.headers[headerKeys.Environment] ?? null;\n }\n\n get appVersion(): string | undefined {\n return this._appVersion;\n }\n\n /**\n * Access the metadata builder for updating run and step metadata.\n *\n * @example\n * ```ts\n * // Update metadata for the current run\n * await inngest.metadata.update({ status: \"processing\" });\n *\n * // Update metadata for a different run\n * await inngest.metadata.run(otherRunId).update({ key: \"val\" });\n *\n * ```\n */\n get metadata(): MetadataBuilder {\n if (!this.experimentalMetadataEnabled) {\n throw new Error(\n 'inngest.metadata is experimental. Enable it by adding metadataMiddleware() from \"inngest/experimental\" to your client middleware.',\n );\n }\n return new UnscopedMetadataBuilder(this);\n }\n\n /**\n * A client used to interact with the Inngest API by sending or reacting to\n * events.\n *\n * ```ts\n * const inngest = new Inngest({ id: \"my-app\" });\n * ```\n */\n constructor(options: TClientOpts) {\n this.options = options;\n\n const { id, logger, middleware, appVersion } = this.options;\n\n if (!id) {\n throw new Error(\"An `id` must be passed to create an Inngest instance.\");\n }\n\n this.id = id;\n this._env = { ...allProcessEnv() };\n this._userProvidedFetch = options.fetch;\n\n this.inngestApi = new InngestApi({\n baseUrl: () => this.apiBaseUrl,\n signingKey: () => this.signingKey,\n signingKeyFallback: () => this.signingKeyFallback,\n fetch: () => this.fetch,\n });\n\n this._logger = logger ?? new ConsoleLogger();\n this[internalLoggerSymbol] = this.options.internalLogger ?? this._logger;\n\n this.middleware = [\n ...builtInMiddleware(this._logger),\n ...(middleware ?? []),\n ];\n\n for (const mw of this.middleware) {\n mw.onRegister?.({ client: this, fn: null });\n }\n\n this._appVersion = appVersion;\n }\n\n /**\n * Returns a `Promise` that resolves when the app is ready and all middleware\n * has been initialized.\n */\n public get ready(): Promise<void> {\n // Previously this was used to ensure that we could wait for middleware\n // to be instantiated, but we now no longer have a set-up function\n // that we await, so middleware is always ready to go.\n return Promise.resolve();\n }\n\n /**\n * Set the environment variables for this client. This is useful if you are\n * passed environment variables at runtime instead of as globals and need to\n * update the client with those values as requests come in.\n */\n public setEnvVars(\n env: Record<string, string | undefined> = allProcessEnv(),\n ): this {\n this._env = { ...this._env, ...env };\n\n return this;\n }\n\n get mode(): Mode {\n if (typeof this.options.isDev === \"boolean\") {\n return this.options.isDev ? \"dev\" : \"cloud\";\n }\n\n const envIsDev = parseAsBoolean(this._env[envKeys.InngestDevMode]);\n if (typeof envIsDev === \"boolean\") {\n return envIsDev ? \"dev\" : \"cloud\";\n }\n\n if (this.explicitDevUrl) {\n return \"dev\";\n }\n\n return \"cloud\";\n }\n\n /**\n * Given a response from Inngest, relay the error to the caller.\n */\n private async getResponseError(\n response: globalThis.Response,\n rawBody: unknown,\n foundErr = \"Unknown error\",\n ): Promise<Error> {\n let errorMessage = foundErr;\n\n if (errorMessage === \"Unknown error\") {\n switch (response.status) {\n case 401:\n errorMessage = \"Event key Not Found\";\n break;\n case 400:\n errorMessage = \"Cannot process event payload\";\n break;\n case 403:\n errorMessage = \"Forbidden\";\n break;\n case 404:\n errorMessage = \"Event key not found\";\n break;\n case 406:\n errorMessage = `${JSON.stringify(await rawBody)}`;\n break;\n case 409:\n case 412:\n errorMessage = \"Event transformation failed\";\n break;\n case 413:\n errorMessage = \"Event payload too large\";\n break;\n case 500:\n errorMessage = \"Internal server error\";\n break;\n default:\n try {\n errorMessage = await response.text();\n } catch (_err) {\n errorMessage = `${JSON.stringify(await rawBody)}`;\n }\n break;\n }\n }\n\n return new Error(`Inngest API Error: ${response.status} ${errorMessage}`);\n }\n\n private eventKeySet(): boolean {\n return this.eventKey !== undefined;\n }\n\n /**\n * EXPERIMENTAL: This API is not yet stable and may change in the future\n * without a major version bump.\n *\n * Send a Signal to Inngest.\n */\n public async sendSignal({\n signal,\n data,\n env,\n }: {\n /**\n * The signal to send.\n */\n signal: string;\n\n /**\n * The data to send with the signal.\n */\n data?: unknown;\n\n /**\n * The Inngest environment to send the signal to. Defaults to whichever\n * environment this client's key is associated with.\n *\n * It's like you never need to change this unless you're trying to sync\n * multiple systems together using branch names.\n */\n env?: string;\n }): Promise<InngestApi.SendSignalResponse> {\n const headers: Record<string, string> = {\n ...(env ? { [headerKeys.Environment]: env } : {}),\n };\n\n return this._sendSignal({ signal, data, headers });\n }\n\n private async _sendSignal({\n signal,\n data,\n headers,\n }: {\n signal: string;\n data?: unknown;\n headers?: Record<string, string>;\n }): Promise<InngestApi.SendSignalResponse> {\n const res = await this.inngestApi.sendSignal(\n { signal, data },\n { ...this.headers, ...headers },\n );\n if (res.ok) {\n return res.value;\n }\n\n throw new Error(\n `Failed to send signal: ${res.error?.error || \"Unknown error\"}`,\n );\n }\n\n private async updateMetadata({\n target,\n metadata,\n headers,\n }: {\n target: MetadataTarget;\n metadata: Array<{\n kind: string;\n op: string;\n values: Record<string, unknown>;\n }>;\n headers?: Record<string, string>;\n }): Promise<void> {\n const res = await this.inngestApi.updateMetadata(\n {\n target,\n metadata,\n },\n { headers },\n );\n if (res.ok) {\n return res.value;\n }\n\n throw new Error(\n `Failed to update metadata: ${res.error?.error || \"Unknown error\"}`,\n );\n }\n\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: used in the SDK\n private async warnMetadata(\n target: MetadataTarget,\n kind: ErrCode,\n log: StructuredLogMessage,\n ) {\n const fields: Record<string, unknown> = {};\n if (log.code) {\n fields.code = log.code;\n }\n if (log.explanation) {\n fields.explanation = log.explanation;\n }\n if (log.action) {\n fields.action = log.action;\n }\n if (log.docs) {\n fields.docs = log.docs;\n }\n\n if (Object.keys(fields).length > 0) {\n this[internalLoggerSymbol].warn(fields, log.message);\n } else {\n this[internalLoggerSymbol].warn(log.message);\n }\n\n if (!this.experimentalMetadataEnabled) {\n return;\n }\n\n await this.updateMetadata({\n target: target,\n metadata: [\n {\n kind: \"inngest.warnings\",\n op: \"merge\",\n values: {\n [`sdk.${kind}`]: formatLogMessage(log),\n },\n },\n ],\n });\n }\n\n /**\n * Realtime-related functionality for this Inngest client.\n */\n public realtime: {\n /**\n * Publish data to a realtime channel topic.\n *\n * This is a non-durable publish, it executes immediately and is not\n * memoized. If called inside an Inngest function, it will automatically\n * include the current run ID. For durable publishing inside functions, use\n * `step.realtime.publish()`.\n *\n * ```ts\n * await inngest.realtime.publish(ch.status, { message: \"Processing...\" });\n * ```\n */\n publish: Realtime.TypedPublishFn;\n\n /**\n * Subscribe to realtime messages on a channel, returning a readable stream.\n */\n subscribe: {\n <\n const InputChannel extends Realtime.ChannelInput,\n const InputTopics extends ChannelTopicsInput<InputChannel>,\n const TToken extends Realtime.Subscribe.Token<\n InputChannel,\n InputTopics\n >,\n >(opts: {\n channel: InputChannel;\n topics: InputTopics;\n validate?: boolean;\n onMessage: Realtime.Subscribe.Callback<TToken>;\n onError?: (err: unknown) => void;\n }): Promise<Realtime.Subscribe.CallbackSubscription>;\n <\n const InputChannel extends Realtime.ChannelInput,\n const InputTopics extends ChannelTopicsInput<InputChannel>,\n const TToken extends Realtime.Subscribe.Token<\n InputChannel,\n InputTopics\n >,\n >(opts: {\n channel: InputChannel;\n topics: InputTopics;\n validate?: boolean;\n }): Promise<Realtime.Subscribe.StreamSubscription<TToken>>;\n };\n\n /**\n * Generate a subscription token for subscribing to realtime messages.\n */\n token: <\n const InputChannel extends Realtime.ChannelInput,\n const InputTopics extends ChannelTopicsInput<InputChannel>,\n const TToken extends Realtime.Subscribe.Token<InputChannel, InputTopics>,\n >(opts: {\n channel: InputChannel;\n topics: InputTopics;\n }) => Promise<TToken>;\n } = {\n publish: async (topicRef, data) => {\n const topicConfig = topicRef.config;\n if (topicConfig && \"schema\" in topicConfig && topicConfig.schema) {\n const result = await topicConfig.schema[\"~standard\"].validate(data);\n if (result.issues) {\n throw new Error(\n `Schema validation failed for topic \"${topicRef.topic}\"`,\n );\n }\n }\n\n const ctx = await getAsyncCtx();\n const runId = ctx?.execution?.ctx.runId;\n\n const res = await this.inngestApi.publish(\n {\n channel: topicRef.channel,\n topics: [topicRef.topic],\n runId,\n },\n data,\n );\n\n if (!res.ok) {\n throw new Error(\n `Failed to publish to realtime: ${\n res.error?.error || \"Unknown error\"\n }`,\n );\n }\n },\n\n subscribe: async (opts) => {\n // biome-ignore lint/suspicious/noExplicitAny: sacrifice for clean generics\n return realtimeSubscribe({ ...opts, app: this } as any) as any;\n },\n\n token: async (opts) => {\n // biome-ignore lint/suspicious/noExplicitAny: sacrifice for clean generics\n return realtimeGetSubscriptionToken(this, opts as any) as any;\n },\n };\n\n public endpoint<THandler extends Inngest.EndpointHandler<this>>(\n handler: THandler,\n ): THandler {\n if (!this.options.endpointAdapter) {\n throw new Error(\n \"No endpoint adapter configured for this Inngest client.\",\n );\n }\n\n return this.options.endpointAdapter({ client: this })(handler);\n }\n\n /**\n * Creates a proxy handler that polls Inngest for durable endpoint results.\n *\n * The proxy:\n * - Extracts `runId` and `token` from query params\n * - Fetches the result from Inngest API\n * - Runs the response through middleware (e.g., decryption)\n * - Adds CORS headers\n *\n * Use this in combination with the `asyncRedirectUrl` option on your\n * endpoint adapter to redirect users to your own proxy endpoint instead\n * of directly to Inngest.\n *\n * @example\n * ```ts\n * import { Inngest } from \"inngest\";\n * import { endpointAdapter } from \"inngest/edge\";\n *\n * const inngest = new Inngest({\n * id: \"my-app\",\n * endpointAdapter: endpointAdapter.withOptions({\n * asyncRedirectUrl: \"/api/inngest/poll\",\n * }),\n * });\n *\n * // Durable endpoint\n * export const GET = inngest.endpoint(async (req) => {\n * const result = await step.run(\"work\", () => \"done\");\n * return new Response(result);\n * });\n *\n * // Proxy endpoint at /api/inngest/poll\n * export const GET = inngest.endpointProxy();\n * ```\n */\n public endpointProxy(): Inngest.ProxyHandler<this> {\n if (!this.options.endpointAdapter) {\n throw new Error(\n \"No endpoint adapter configured for this Inngest client.\",\n );\n }\n\n if (!this.options.endpointAdapter.createProxyHandler) {\n throw new Error(\n \"The configured endpoint adapter does not support proxy handlers.\",\n );\n }\n\n return this.options.endpointAdapter.createProxyHandler({ client: this });\n }\n\n /**\n * Decrypt a proxy response using the client's middleware stack.\n *\n * Runs `transformFunctionInput` on each middleware instance to decrypt\n * step data (used by encryption middleware).\n *\n * Uses type assertions because we're creating a minimal \"fake\" execution\n * context just to run the decryption middleware hooks - not a full execution.\n *\n * @internal\n */\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via bracket notation by InngestProxyHandler\n private async decryptProxyResult<T extends { data?: unknown }>(\n result: T,\n ): Promise<T> {\n if (!result.data) {\n return result;\n }\n\n const mwInstances = this.middleware.map((Cls) => {\n return new Cls({ client: this });\n });\n\n const dummyEvent = { name: \"__proxy__\", data: {} };\n const dummyCtx = {\n event: dummyEvent,\n events: [dummyEvent],\n runId: \"__proxy__\",\n attempt: 0,\n step,\n } as unknown as BaseContext<Inngest.Any>;\n\n let transformArgs: Middleware.TransformFunctionInputArgs = {\n ctx: dummyCtx,\n fn: this.getDummyDurableEndpointFunction(),\n steps: {\n __result__: { type: \"data\" as const, data: result.data },\n },\n };\n\n for (const mw of mwInstances) {\n if (mw.transformFunctionInput) {\n transformArgs = await mw.transformFunctionInput(transformArgs);\n }\n }\n\n const decryptedStep = transformArgs.steps?.__result__;\n let decryptedData = result.data;\n if (decryptedStep && \"data\" in decryptedStep) {\n decryptedData = decryptedStep.data as typeof decryptedData;\n }\n\n return { ...result, data: decryptedData };\n }\n\n /**\n * Send one or many events to Inngest. Takes an entire payload (including\n * name) as each input.\n *\n * ```ts\n * await inngest.send({ name: \"app/user.created\", data: { id: 123 } });\n * ```\n *\n * Returns a promise that will resolve if the event(s) were sent successfully,\n * else throws with an error explaining what went wrong.\n */\n public async send(\n payload: SendEventPayload,\n options?: {\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 ): Promise<SendEventOutput<TClientOpts>> {\n const headers: Record<string, string> = {\n ...(options?.env ? { [headerKeys.Environment]: options.env } : {}),\n };\n\n return this._send({\n payload,\n headers,\n fnMiddleware: [],\n fn: null,\n });\n }\n\n /**\n * Internal method for sending an event, used to allow Inngest internals to\n * further customize the request sent to an Inngest Server.\n */\n private async _send({\n payload,\n headers,\n fn,\n fnMiddleware,\n }: {\n payload: SendEventPayload;\n headers?: Record<string, string>;\n fn: InngestFunction.Any | null;\n fnMiddleware: Middleware.Class[];\n }): Promise<SendEventOutput<TClientOpts>> {\n const nowMillis = new Date().getTime();\n\n let maxAttempts = 5;\n\n // Attempt to set the event ID seed header. If it fails then disable retries\n // (but we still want to send the event).\n try {\n const entropy = createEntropy(10);\n const entropyBase64 = Buffer.from(entropy).toString(\"base64\");\n headers = {\n ...headers,\n [headerKeys.EventIdSeed]: `${nowMillis},${entropyBase64}`,\n };\n } catch (err) {\n this[internalLoggerSymbol].debug(\n { err },\n \"Event-sending retries disabled\",\n );\n\n // Disable retries.\n maxAttempts = 1;\n }\n\n let payloads: EventPayload[] = Array.isArray(payload)\n ? (payload as EventPayload[])\n : payload\n ? ([payload] as [EventPayload])\n : [];\n\n // Instantiate fresh middleware per send() call.\n const mwInstances = [...this.middleware, ...fnMiddleware].map(\n (Cls) => new Cls({ client: this }),\n );\n for (const mw of mwInstances) {\n if (mw?.transformSendEvent) {\n const transformed = await mw.transformSendEvent({\n events: payloads,\n fn: fn ?? null,\n });\n if (transformed !== undefined) {\n payloads = transformed.events;\n }\n }\n }\n\n // Validate payloads that have a validate method (from `EventType.create()`)\n for (const payload of payloads) {\n if (isValidatable(payload)) {\n await payload.validate();\n }\n }\n\n // Ensure that we always add \"ts\" and \"data\" fields to events. \"ts\" is auto-\n // filled by the event server so is safe, and adding here fixes Next.js\n // server action cache issues.\n payloads = payloads.map((p) => {\n return {\n ...p,\n // Always generate an idempotency ID for an event for retries\n id: p.id,\n ts: p.ts || nowMillis,\n data: p.data || {},\n };\n });\n\n /**\n * It can be valid for a user to send an empty list of events; if this\n * happens, show a warning that this may not be intended, but don't throw.\n */\n if (!payloads.length) {\n this[internalLoggerSymbol].warn(\n \"inngest.send() called with no events; the returned promise will resolve, but no events have been sent\",\n );\n\n return { ids: [] } as SendEventOutput<TClientOpts>;\n }\n\n /**\n * If in prod mode and key is not present, fail now.\n */\n if (this.mode === \"cloud\" && !this.eventKeySet()) {\n throw new Error(\n formatLogMessage({\n message: \"Failed to send event\",\n explanation:\n \"Your event or events were not sent to Inngest. We couldn't find an event key to use to send events to Inngest.\",\n action: fixEventKeyMissingSteps.join(\"; \"),\n }),\n );\n }\n\n const innerHandler = async () => {\n const body = await retryWithBackoff(\n async () => {\n let rawBody: unknown;\n let body: SendEventResponse | undefined;\n\n // We don't need to do fallback auth here because this uses event keys and\n // not signing keys\n const url = new URL(\n `e/${this.eventKey ?? dummyEventKey}`,\n this.eventBaseUrl,\n );\n const response = await this.fetch(url.href, {\n method: \"POST\",\n body: stringify(payloads),\n headers: { ...this.headers, ...headers },\n });\n\n try {\n rawBody = await response.json();\n body = await sendEventResponseSchema.parseAsync(rawBody);\n } catch (_err) {\n throw await this.getResponseError(response, rawBody);\n }\n\n if (body.status !== 200 || body.error) {\n throw await this.getResponseError(response, rawBody, body.error);\n }\n\n return body;\n },\n {\n maxAttempts,\n baseDelay: 100,\n },\n );\n\n return { ids: body.ids } as SendEventOutput<TClientOpts>;\n };\n\n const wrappedHandler = buildWrapSendEventChain(\n mwInstances,\n innerHandler,\n payloads,\n fn,\n );\n\n return (await wrappedHandler()) as SendEventOutput<TClientOpts>;\n }\n\n public createFunction: Inngest.CreateFunction<this> = (\n rawOptions,\n handler,\n ) => {\n const fn = this._createFunction(rawOptions, handler);\n\n for (const mw of fn.opts.middleware ?? []) {\n mw.onRegister?.({ client: this, fn });\n }\n\n this.localFns.push(fn);\n\n return fn;\n };\n\n public get funcs() {\n return this.localFns;\n }\n\n private _createFunction: Inngest.CreateFunction<this> = (\n rawOptions,\n handler,\n ) => {\n if (typeof handler !== \"function\") {\n throw new Error(\n `\"createFunction\" expected a handler function as the second argument. Triggers belong in the first argument: createFunction({ id, triggers: { event: \"...\" } }, handler)`,\n );\n }\n\n const options = {\n ...rawOptions,\n triggers: this.sanitizeTriggers(rawOptions.triggers),\n };\n\n return new InngestFunction(this, options, handler);\n };\n\n /**\n * Runtime-only validation.\n */\n private sanitizeTriggers<\n T extends SingleOrArray<InngestFunction.Trigger<string>> | undefined,\n >(\n triggers: T | undefined,\n ): T extends undefined ? [] : AsArray<NonNullable<T>> {\n type Result = T extends undefined ? [] : AsArray<NonNullable<T>>;\n\n if (triggers === undefined) {\n return [] as Result;\n }\n\n if (!Array.isArray(triggers)) {\n return [triggers] as Result;\n }\n\n return triggers as Result;\n }\n}\n\n/**\n * Default middleware that is included in every client, placed before the user's\n * middleware. Returns new-style `Middleware.Class` constructors. Uses a closure\n * so the no-arg constructors can capture the base logger.\n */\nexport function builtInMiddleware(baseLogger: Logger) {\n return [\n class LoggerMiddleware extends Middleware.BaseMiddleware {\n readonly id = \"inngest:logger\";\n proxyLogger = new ProxyLogger(baseLogger);\n\n override transformFunctionInput(\n arg: Middleware.TransformFunctionInputArgs,\n ) {\n let logger: Logger = baseLogger;\n\n // Create a child logger with run metadata if supported\n if (\"child\" in logger) {\n try {\n logger = (\n logger.child as (meta: Record<string, unknown>) => Logger\n )({\n runID: arg.ctx.runId,\n eventName: arg.ctx.event.name,\n });\n } catch (err) {\n logger.error({ err }, 'failed to create \"childLogger\" with error');\n }\n }\n\n this.proxyLogger = new ProxyLogger(logger);\n\n return {\n ...arg,\n ctx: Object.assign({}, arg.ctx, {\n logger: this.proxyLogger as Logger,\n }),\n };\n }\n\n override onMemoizationEnd() {\n this.proxyLogger.enable();\n }\n\n override onStepError(arg: Middleware.OnStepErrorArgs) {\n this.proxyLogger.error({ err: arg.error }, \"Inngest step error\");\n }\n\n override wrapFunctionHandler({\n next,\n }: Middleware.WrapFunctionHandlerArgs) {\n return next().catch((err: unknown) => {\n this.proxyLogger.error({ err }, \"Inngest function error\");\n throw err;\n });\n }\n\n override wrapRequest({ next }: Middleware.WrapRequestArgs) {\n return next().finally(() => this.proxyLogger.flush());\n }\n },\n ] as const;\n}\n\n/**\n * A client used to interact with the Inngest API by sending or reacting to\n * events.\n *\n * ```ts\n * const inngest = new Inngest({ id: \"my-app\" });\n * ```\n *\n * @public\n */\nexport namespace Inngest {\n export const Tag = \"Inngest.App\" as const;\n\n /**\n * Represents any `Inngest` instance, regardless of generics and inference.\n *\n * Prefer use of `Inngest.Like` where possible to ensure compatibility with\n * multiple versions.\n */\n export type Any = Inngest;\n\n /**\n * References any `Inngest` instance across library versions, useful for use\n * in public APIs to ensure compatibility with multiple versions.\n *\n * Prefer use of `Inngest.Any` internally and `Inngest.Like` for public APIs.\n */\n export interface Like {\n readonly [Symbol.toStringTag]: typeof Inngest.Tag;\n }\n\n export type EndpointHandler<TClient extends Inngest.Any> = ReturnType<\n NonNullable<ClientOptionsFromInngest<TClient>[\"endpointAdapter\"]>\n >;\n\n type ResolveTriggers<T> = T extends undefined ? [] : AsArray<NonNullable<T>>;\n\n /**\n * Input type for createFunction that accepts raw trigger input (single, array, or undefined)\n * while keeping all other fields from InngestFunction.Options.\n */\n export type CreateFunctionInput<\n TFnMiddleware extends Middleware.Class[] | undefined,\n TTriggers extends\n | SingleOrArray<InngestFunction.Trigger<string>>\n | undefined,\n TFailureHandler extends Handler.Any,\n > = Omit<\n InngestFunction.Options<InngestFunction.Trigger<string>[], TFailureHandler>,\n \"triggers\"\n > & {\n triggers?: TTriggers;\n middleware?: TFnMiddleware;\n };\n\n /**\n * The type of the proxy handler returned by `endpointProxy()`.\n *\n * This type is inferred from the `createProxyHandler` function of the\n * endpoint adapter configured on the client.\n */\n export type ProxyHandler<TClient extends Inngest.Any> = ReturnType<\n NonNullable<\n NonNullable<\n ClientOptionsFromInngest<TClient>[\"endpointAdapter\"]\n >[\"createProxyHandler\"]\n >\n >;\n\n export type CreateFunction<TClient extends Inngest.Any> = <\n const TTriggers extends\n | SingleOrArray<InngestFunction.Trigger<string>>\n | undefined = undefined,\n const TFnMiddleware extends Middleware.Class[] | undefined = undefined,\n THandler extends Handler.Any = HandlerWithTriggers<\n ReturnType<typeof createStepTools<TClient, TFnMiddleware>>,\n ResolveTriggers<TTriggers>,\n ApplyAllMiddlewareCtxExtensions<\n [...ReturnType<typeof builtInMiddleware>]\n > &\n ApplyAllMiddlewareCtxExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > & {\n step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> &\n ApplyAllMiddlewareStepExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n >;\n }\n >,\n TFailureHandler extends Handler.Any = HandlerWithTriggers<\n ReturnType<typeof createStepTools<TClient, TFnMiddleware>>,\n ResolveTriggers<TTriggers>,\n ApplyAllMiddlewareCtxExtensions<\n [...ReturnType<typeof builtInMiddleware>]\n > &\n FailureEventArgs<EventPayload> &\n ApplyAllMiddlewareCtxExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > & {\n step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> &\n ApplyAllMiddlewareStepExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n >;\n }\n >,\n >(\n options: CreateFunctionInput<TFnMiddleware, TTriggers, TFailureHandler>,\n handler: THandler,\n ) => InngestFunction<\n InngestFunction.Options<ResolveTriggers<TTriggers>, TFailureHandler>,\n THandler,\n TFailureHandler,\n TClient,\n ResolveTriggers<TTriggers>\n >;\n}\n\n/**\n * A helper type to extract the type of a set of event tooling from a given\n * Inngest instance and optionally a trigger.\n *\n * @example Get generic step tools for an Inngest instance.\n * ```ts\n * type StepTools = GetStepTools<typeof inngest>;\n * ```\n *\n * @example Get step tools with a trigger, ensuring tools like `waitForEvent` are typed.\n * ```ts\n * type StepTools = GetStepTools<typeof Inngest, \"github/pull_request\">;\n * ```\n *\n * @public\n */\nexport type GetStepTools<TInngest extends Inngest.Any> =\n GetFunctionInput<TInngest> extends { step: infer TStep } ? TStep : never;\n\n/**\n * A helper type to extract the type of the input to a function from a given\n * Inngest instance and optionally a trigger.\n *\n * @example Get generic function input for an Inngest instance.\n * ```ts\n * type Input = GetFunctionInput<typeof inngest>;\n * ```\n *\n * @example Get function input with a trigger, ensuring tools like `waitForEvent` are typed.\n * ```ts\n * type Input = GetFunctionInput<typeof Inngest, \"github/pull_request\">;\n * ```\n *\n * @public\n */\nexport type GetFunctionInput<TClient extends Inngest.Any> = Parameters<\n Handler<\n TClient,\n ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> &\n ApplyAllMiddlewareCtxExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > & {\n step: ReturnType<typeof createStepTools<TClient>> &\n ApplyAllMiddlewareStepExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n >;\n }\n >\n>[0];\n\n/**\n * A helper type to extract the type of the output of an Inngest function.\n *\n * @example Get a function's output\n * ```ts\n * type Output = GetFunctionOutput<typeof myFunction>;\n * ```\n *\n * @public\n */\nexport type GetFunctionOutput<\n TFunction extends InvokeTargetFunctionDefinition,\n> = TFunction extends InngestFunction.Any\n ? GetFunctionOutputFromInngestFunction<TFunction>\n : TFunction extends InngestFunctionReference.Any\n ? GetFunctionOutputFromReferenceInngestFunction<TFunction>\n : unknown;\n\n/**\n * A helper type to extract the type of the output of an Inngest function.\n *\n * Used internally for {@link GetFunctionOutput}. Code outside of this package\n * should use {@link GetFunctionOutput} instead.\n *\n * @internal\n */\nexport type GetFunctionOutputFromInngestFunction<\n TFunction extends InngestFunction.Any,\n> = TFunction extends InngestFunction<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n any,\n infer IHandler,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n any,\n infer TClient,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n any\n>\n ? IsNever<\n VoidToNull<SimplifyDeep<Awaited<ReturnType<IHandler>>>>\n > extends true\n ? null\n : ApplyAllMiddlewareTransforms<\n ClientOptionsFromInngest<TClient>[\"middleware\"],\n VoidToNull<SimplifyDeep<Awaited<ReturnType<IHandler>>>>,\n \"functionOutputTransform\"\n >\n : unknown;\n\n/**\n * A helper type to extract the type of the output of a referenced Inngest\n * function.\n *\n * Used internally for {@link GetFunctionOutput}. Code outside of this package\n * should use {@link GetFunctionOutput} instead.\n *\n * @internal\n */\nexport type GetFunctionOutputFromReferenceInngestFunction<\n TFunction extends InngestFunctionReference.Any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n> = TFunction extends InngestFunctionReference<any, infer IOutput>\n ? IsNever<SimplifyDeep<Jsonify<IOutput>>> extends true\n ? null\n : SimplifyDeep<Jsonify<IOutput>>\n : unknown;\n\n/**\n * A helper type to extract the raw (non-Jsonified) output type of an Inngest\n * function. This is used when middleware transforms will handle serialization.\n *\n * @internal\n */\nexport type GetFunctionOutputRaw<\n TFunction extends InvokeTargetFunctionDefinition,\n> = TFunction extends InngestFunction.Any\n ? GetFunctionOutputRawFromInngestFunction<TFunction>\n : TFunction extends InngestFunctionReference.Any\n ? GetFunctionOutputRawFromReferenceInngestFunction<TFunction>\n : unknown;\n\n/**\n * @internal\n */\nexport type GetFunctionOutputRawFromInngestFunction<\n TFunction extends InngestFunction.Any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n> = TFunction extends InngestFunction<any, infer IHandler, any, any, any>\n ? VoidToNull<Awaited<ReturnType<IHandler>>>\n : unknown;\n\n/**\n * @internal\n */\nexport type GetFunctionOutputRawFromReferenceInngestFunction<\n TFunction extends InngestFunctionReference.Any,\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n> = TFunction extends InngestFunctionReference<any, infer IOutput>\n ? VoidToNull<SimplifyDeep<IOutput>>\n : unknown;\n\n/**\n * Helper type that converts void/undefined/never to null.\n * Uses ReturnType trick to check for void without directly using void in type position.\n * @internal\n */\ntype VoidToNull<T> = IsNever<T> extends true\n ? null\n : T extends ReturnType<() => void>\n ? null\n : T;\n\n/**\n * A helper type to extract the inferred options from a given Inngest instance.\n *\n * @example\n * ```ts\n * type Options = ClientOptionsFromInngest<typeof inngest>;\n * ```\n *\n * @public\n */\n\nexport type ClientOptionsFromInngest<TInngest extends Inngest.Any> =\n TInngest extends Inngest<infer U> ? U : ClientOptions;\n"],"mappings":"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