import { ExecutionVersion } from "../helpers/consts.cjs";
import { MaybePromise } from "../helpers/types.cjs";
import { ServerTiming } from "../helpers/ServerTiming.cjs";
import { Middleware } from "./middleware/middleware.cjs";
import { ExecutionResult, InngestExecutionOptions } from "./execution/InngestExecution.cjs";
import { InngestFunction } from "./InngestFunction.cjs";
import { AsyncResponseValue, AuthenticatedIntrospection, DefaultMaxRuntime, FunctionConfig, InBandRegisterRequest, RegisterOptions, RegisterRequest, UnauthenticatedIntrospection } from "../types.cjs";
import { Inngest } from "./Inngest.cjs";
import { Env } from "../helpers/env.cjs";

//#region src/components/InngestCommHandler.d.ts

/**
 * An entry in the function registry, tracking which config ID maps to which
 * function and what kind of handler it is (main, failure, or defer).
 */
interface FnRegistryEntry {
  fn: InngestFunction.Any;
  handlerKind: "main" | "failure" | "defer";
}
/**
 * A set of options that can be passed to a serve handler, intended to be used
 * by internal and custom serve handlers to provide a consistent interface.
 *
 * @public
 */
interface ServeHandlerOptions extends RegisterOptions {
  /**
   * The `Inngest` instance used to declare all functions.
   */
  client: Inngest.Like;
  /**
   * An array of the functions to serve and register with Inngest.
   */
  functions: readonly InngestFunction.Like[];
}
/**
 * Parameters passed to the asyncRedirectUrl function.
 */
interface AsyncRedirectUrlParams {
  /**
   * The unique identifier for this run.
   */
  runId: string;
  /**
   * The token used to authenticate the request to fetch run output.
   */
  token: string;
}
interface SyncHandlerOptions extends RegisterOptions {
  /**
   * The `Inngest` instance used to declare all functions.
   */
  client: Inngest.Like;
  /**
   * The type of response you wish to return to an API endpoint when using steps
   * within it and we must transition to {@link StepMode.Async}.
   *
   * In most cases, this defaults to {@link AsyncResponseType.Redirect}.
   */
  asyncResponse?: AsyncResponseValue;
  /**
   * Custom URL to redirect to when switching from sync to async mode.
   *
   * Can be:
   * - A string path (e.g., "/api/inngest/poll") - resolved relative to request origin
   * - A function that receives `{ runId, token }` and returns a full URL
   *
   * When a string path is provided, `runId` and `token` query parameters are
   * automatically appended.
   *
   * @example
   * ```ts
   * // String path - resolved relative to request origin
   * asyncRedirectUrl: "/api/inngest/poll"
   *
   * // Function - full control over URL construction
   * asyncRedirectUrl: ({ runId, token }) =>
   *   `https://my-app.com/poll?run=${runId}&t=${token}`
   * ```
   */
  asyncRedirectUrl?: string | ((params: AsyncRedirectUrlParams) => string | Promise<string>);
  /**
   * If defined, this sets the function ID that represents this endpoint.
   * Without this set, it defaults to using the detected method and path of the
   * request, for example: `GET /api/my-endpoint`.
   */
  functionId?: string;
  /**
   * Specifies the maximum number of retries for all steps.
   *
   * Can be a number from `0` to `20`. Defaults to `3`.
   */
  retries?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20;
}
type SyncAdapterOptions = Omit<SyncHandlerOptions, "client">;
interface InngestCommHandlerOptions<Input extends any[] = any[], Output = any, StreamOutput = any> extends RegisterOptions {
  /**
   * The name of the framework this handler is designed for. Should be
   * lowercase, alphanumeric characters inclusive of `-` and `/`.
   *
   * This should never be defined by the user; a {@link ServeHandler} should
   * abstract this.
   */
  frameworkName: string;
  /**
   * The name of this serve handler, e.g. `"My App"`. It's recommended that this
   * value represents the overarching app/service that this set of functions is
   * being served from.
   *
   * This can also be an `Inngest` client, in which case the name given when
   * instantiating the client is used. This is useful if you're sending and
   * receiving events from the same service, as you can reuse a single
   * definition of Inngest.
   */
  client: Inngest.Like;
  /**
   * An array of the functions to serve and register with Inngest.
   */
  functions?: readonly InngestFunction.Like[];
  /**
   * The `handler` is the function that will be called with your framework's
   * request arguments and returns a set of functions that the SDK will use to
   * access various parts of the request, such as the body, headers, and query
   * string parameters.
   *
   * It also defines how to transform a response from the SDK into a response
   * that your framework can understand, ensuring headers, status codes, and
   * body are all set correctly.
   *
   * @example
   * ```ts
   * function handler (req: Request, res: Response) {
   *   return {
   *     method: () => req.method,
   *     body: () => req.json(),
   *     headers: (key) => req.headers.get(key),
   *     url: () => req.url,
   *     transformResponse: ({ body, headers, status }) => {
   *       return new Response(body, { status, headers });
   *     },
   *   };
   * };
   * ```
   *
   * See any existing handler for a full example.
   */
  handler: Handler<Input, Output, StreamOutput>;
  skipSignatureValidation?: boolean;
  /**
   * The default `maxRuntime` in milliseconds to use for checkpointing when the
   * user hasn't explicitly configured one at the function or client level.
   *
   * Defaults to {@link DefaultMaxRuntime.serve} (10 seconds).
   */
  defaultMaxRuntime?: DefaultMaxRuntime;
  /**
   * Options for when this comm handler executes a synchronous (API) function.
   */
  syncOptions?: SyncHandlerOptions;
}
/**
 * `InngestCommHandler` is a class for handling incoming requests from Inngest (or
 * Inngest's tooling such as the dev server or CLI) and taking appropriate
 * action for any served functions.
 *
 * All handlers (Next.js, RedwoodJS, Remix, Deno Fresh, etc.) are created using
 * this class; the exposed `serve` function will - most commonly - create an
 * instance of `InngestCommHandler` and then return `instance.createHandler()`.
 *
 * See individual parameter details for more information, or see the
 * source code for an existing handler, e.g.
 * {@link https://github.com/inngest/inngest-js/blob/main/src/next.ts}
 *
 * @example
 * ```
 * // my-custom-handler.ts
 * import {
 *   InngestCommHandler,
 *   type ServeHandlerOptions,
 * } from "./components/InngestCommHandler";
 *
 * export const serve = (options: ServeHandlerOptions) => {
 *   const handler = new InngestCommHandler({
 *     frameworkName: "my-custom-handler",
 *     ...options,
 *     handler: (req: Request) => {
 *       return {
 *         body: () => req.json(),
 *         headers: (key) => req.headers.get(key),
 *         method: () => req.method,
 *         url: () => new URL(req.url, `https://${req.headers.get("host") || ""}`),
 *         transformResponse: ({ body, status, headers }) => {
 *           return new Response(body, { status, headers });
 *         },
 *       };
 *     },
 *   });
 *
 *   return handler.createHandler();
 * };
 * ```
 *
 * @public
 */
declare class InngestCommHandler<Input extends any[] = any[], Output = any, StreamOutput = any> {
  /**
   * The handler specified during instantiation of the class.
   */
  readonly handler: Handler;
  /**
   * The URL of the Inngest function registration endpoint.
   */
  private readonly inngestRegisterUrl;
  /**
   * The name of the framework this handler is designed for. Should be
   * lowercase, alphanumeric characters inclusive of `-` and `/`.
   */
  protected readonly frameworkName: string;
  /**
   * The origin used to access the Inngest serve endpoint, e.g.:
   *
   *     "https://myapp.com" or "https://myapp.com:1234"
   *
   * By default, the library will try to infer this using request details such
   * as the "Host" header and request path, but sometimes this isn't possible
   * (e.g. when running in a more controlled environments such as AWS Lambda or
   * when dealing with proxies/redirects).
   *
   * Provide the custom origin here to ensure that the path is reported
   * correctly when registering functions with Inngest.
   *
   * To also provide a custom path, use `servePath`.
   */
  private readonly _serveOrigin;
  /**
   * The path to the Inngest serve endpoint. e.g.:
   *
   *     "/some/long/path/to/inngest/endpoint"
   *
   * By default, the library will try to infer this using request details such
   * as the "Host" header and request path, but sometimes this isn't possible
   * (e.g. when running in a more controlled environments such as AWS Lambda or
   * when dealing with proxies/redirects).
   *
   * Provide the custom path (excluding the hostname) here to ensure that the
   * path is reported correctly when registering functions with Inngest.
   *
   * To also provide a custom hostname, use `serveOrigin`.
   */
  private readonly _servePath;
  protected readonly streaming: RegisterOptions["streaming"];
  /**
   * A private collection of just Inngest functions, as they have been passed
   * when instantiating the class.
   */
  private readonly rawFns;
  private readonly client;
  /**
   * A private collection of functions that are being served. This map is used
   * to find and register functions when interacting with Inngest Cloud.
   */
  private readonly fns;
  private env;
  private allowExpiredSignatures;
  private readonly _options;
  private readonly skipSignatureValidation;
  private readonly defaultMaxRuntime;
  constructor(options: InngestCommHandlerOptions<Input, Output, StreamOutput>);
  /**
   * The origin used to access the Inngest serve endpoint, e.g.:
   *
   *     "https://myapp.com"
   *
   * By default, the library will try to infer this using request details such
   * as the "Host" header and request path, but sometimes this isn't possible
   * (e.g. when running in a more controlled environments such as AWS Lambda or
   * when dealing with proxies/redirects).
   *
   * Provide the custom origin here to ensure that the path is reported
   * correctly when registering functions with Inngest.
   *
   * To also provide a custom path, use `servePath`.
   */
  protected get serveOrigin(): string | undefined;
  /**
   * The path to the Inngest serve endpoint. e.g.:
   *
   *     "/some/long/path/to/inngest/endpoint"
   *
   * By default, the library will try to infer this using request details such
   * as the "Host" header and request path, but sometimes this isn't possible
   * (e.g. when running in a more controlled environments such as AWS Lambda or
   * when dealing with proxies/redirects).
   *
   * Provide the custom path (excluding the hostname) here to ensure that the
   * path is reported correctly when registering functions with Inngest.
   *
   * To also provide a custom hostname, use `serveOrigin`.
   *
   * This is a getter to encourage checking the environment for the serve path
   * each time it's accessed, as it may change during execution.
   */
  protected get servePath(): string | undefined;
  private get hashedEventKey();
  private get hashedSigningKey();
  private get hashedSigningKeyFallback();
  /**
   * Returns a `boolean` representing whether this handler will stream responses
   * or not. Takes into account the user's preference and the platform's
   * capabilities.
   */
  private shouldStream;
  private isInngestReq;
  /**
   * Start handling a request, setting up environments, modes, and returning
   * some helpers.
   */
  private initRequest;
  /**
   * `createSyncHandler` should be used to return a type-equivalent version of
   * the `handler` specified during instantiation.
   */
  createSyncHandler<THandler extends (...args: Input) => Promise<Awaited<Output>>>(): (handler: THandler) => THandler;
  /**
   * `createHandler` should be used to return a type-equivalent version of the
   * `handler` specified during instantiation.
   *
   * @example
   * ```
   * // my-custom-handler.ts
   * import {
   *   InngestCommHandler,
   *   type ServeHandlerOptions,
   * } from "./components/InngestCommHandler";
   *
   * export const serve = (options: ServeHandlerOptions) => {
   *   const handler = new InngestCommHandler({
   *     frameworkName: "my-custom-handler",
   *     ...options,
   *     handler: (req: Request) => {
   *       return {
   *         body: () => req.json(),
   *         headers: (key) => req.headers.get(key),
   *         method: () => req.method,
   *         url: () => new URL(req.url, `https://${req.headers.get("host") || ""}`),
   *         transformResponse: ({ body, status, headers }) => {
   *           return new Response(body, { status, headers });
   *         },
   *       };
   *     },
   *   });
   *
   *   return handler.createHandler();
   * };
   * ```
   */
  createHandler<THandler extends (...args: Input) => Promise<Awaited<Output>>>(): THandler;
  /**
   * Given a set of actions that let us access the incoming request, create an
   * event that repesents a run starting from an HTTP request.
   */
  private createHttpEvent;
  private handleSyncRequest;
  private handleAsyncRequest;
  private getActions;
  private wrapHandler;
  /**
   * Given a set of functions to check if an action is available from the
   * instance's handler, enact any action that is found.
   *
   * This method can fetch varying payloads of data, but ultimately is the place
   * where _decisions_ are made regarding functionality.
   *
   * For example, if we find that we should be viewing the UI, this function
   * will decide whether the UI should be visible based on the payload it has
   * found (e.g. env vars, options, etc).
   */
  private handleAction;
  protected runStep({
    actions,
    functionId,
    stepId,
    data,
    timer,
    reqArgs,
    headers,
    fn,
    forceExecution,
    headerReqVersion,
    requestInfo,
    mwInstances
  }: {
    actions: HandlerResponseWithErrors;
    functionId: string;
    stepId: string | null;
    data: unknown;
    timer: ServerTiming;
    reqArgs: unknown[];
    headers: Record<string, string>;
    fn: FnRegistryEntry;
    forceExecution: boolean;
    headerReqVersion?: ExecutionVersion;
    requestInfo?: InngestExecutionOptions["requestInfo"];
    mwInstances?: Middleware.BaseMiddleware[];
  }): {
    version: ExecutionVersion;
    result: Promise<ExecutionResult>;
  };
  protected configs(url: URL): FunctionConfig[];
  /**
   * Return an Inngest serve endpoint URL given a potential `path` and `host`.
   *
   * Will automatically use the `serveOrigin` and `servePath` if they have been
   * set when registering.
   */
  protected reqUrl(url: URL): URL;
  protected registerBody({
    url,
    deployId
  }: {
    url: URL;
    /**
     * Non-optional to ensure we always consider if we have a deploy ID
     * available to us to use.
     */
    deployId: string | undefined | null;
  }): RegisterRequest;
  protected inBandRegisterBody({
    actions,
    deployId,
    env,
    signatureValidation,
    url
  }: {
    actions: HandlerResponseWithErrors;
    /**
     * Non-optional to ensure we always consider if we have a deploy ID
     * available to us to use.
     */
    deployId: string | undefined | null;
    env: string | null;
    signatureValidation: ReturnType<InngestCommHandler["validateSignature"]>;
    url: URL;
  }): Promise<InBandRegisterRequest>;
  protected introspectionBody({
    actions,
    env,
    signatureValidation,
    url
  }: {
    actions: HandlerResponseWithErrors;
    env: string | null;
    signatureValidation: ReturnType<InngestCommHandler["validateSignature"]>;
    url: URL;
  }): Promise<UnauthenticatedIntrospection | AuthenticatedIntrospection>;
  protected register(url: URL, deployId: string | undefined | null, getHeaders: () => Promise<Record<string, string>>): Promise<{
    status: number;
    message: string;
    modified: boolean;
  }>;
  /**
   * Check that the current mode has the configuration it requires.
   * Returns `true` if valid, `false` if not.
   */
  checkModeConfiguration(): boolean;
  /**
   * Validate the signature of a request and return the signing key used to
   * validate it.
   */
  protected validateSignature(sig: string | undefined, body: unknown): Promise<{
    success: true;
    keyUsed: string;
  } | {
    success: false;
    err: Error;
  }>;
  protected getResponseSignature(key: string, body: string): Promise<string>;
}
/**
 * The broad definition of a handler passed when instantiating an
 * {@link InngestCommHandler} instance.
 */
type Handler<Input extends any[] = any[], Output = any, StreamOutput = any> = (...args: Input) => HandlerResponse<Output, StreamOutput>;
type HandlerResponse<Output = any, StreamOutput = any> = {
  body: () => MaybePromise<any>;
  env?: () => MaybePromise<Env | undefined>;
  headers: (key: string) => MaybePromise<string | null | undefined>;
  method: () => MaybePromise<string>;
  queryString?: (key: string, url: URL) => MaybePromise<string | null | undefined>;
  url: () => MaybePromise<URL>;
  /**
   * The `transformResponse` function receives the output of the Inngest SDK and
   * can decide how to package up that information to appropriately return the
   * information to Inngest.
   *
   * Mostly, this is taking the given parameters and returning a new `Response`.
   *
   * The function is passed an {@link ActionResponse}, an object containing a
   * `status` code, a `headers` object, and a stringified `body`. This ensures
   * you can appropriately handle the response, including use of any required
   * parameters such as `res` in Express-/Connect-like frameworks.
   */
  transformResponse: (res: ActionResponse<string>) => Output;
  /**
   * The `transformStreamingResponse` function, if defined, declares that this
   * handler supports streaming responses back to Inngest. This is useful for
   * functions that are expected to take a long time, as edge streaming can
   * often circumvent restrictive request timeouts and other limitations.
   *
   * If your handler does not support streaming, do not define this function.
   *
   * It receives the output of the Inngest SDK and can decide how to package
   * up that information to appropriately return the information in a stream
   * to Inngest.
   *
   * Mostly, this is taking the given parameters and returning a new `Response`.
   *
   * The function is passed an {@link ActionResponse}, an object containing a
   * `status` code, a `headers` object, and `body`, a `ReadableStream`. This
   * ensures you can appropriately handle the response, including use of any
   * required parameters such as `res` in Express-/Connect-like frameworks.
   */
  transformStreamingResponse?: (res: ActionResponse<ReadableStream>) => StreamOutput;
  /**
   * TODO Needed to give folks a chance to wrap arguments if they need to in
   * order to extract the request body so that it can be sent back to Inngest
   * during either sync or async calls.
   *
   * This is because usually they do not interact directly with e.g. the
   * `Response` object, but with sync mode they do, so we need to provide hooks
   * to let us access the body.
   */
  experimentalTransformSyncRequest?: (...args: unknown[]) => MaybePromise<unknown>;
  /**
   * TODO Needed to give folks a chance to transform the response from their own
   * code to an Inngestish response. This is only needed so that sync mode can
   * checkpoint the response if we've gone through the entire run with no
   * interruptions.
   *
   * Because of its location when being specified, we have scoped access to the
   * `reqArgs` (e.g. `req` and `res`), so we don't need to pass them here.
   */
  experimentalTransformSyncResponse?: (data: unknown) => MaybePromise<Omit<ActionResponse, "version">>;
};
/**
 * The response from the Inngest SDK before it is transformed in to a
 * framework-compatible response by an {@link InngestCommHandler} instance.
 */
interface ActionResponse<TBody extends string | ReadableStream = string> {
  /**
   * The HTTP status code to return.
   */
  status: number;
  /**
   * The headers to return in the response.
   */
  headers: Record<string, string>;
  /**
   * A stringified body to return.
   */
  body: TBody;
  /**
   * The version of the execution engine that was used to run this action.
   *
   * If the action didn't use the execution engine (for example, a GET request
   * as a health check) or would have but errored before reaching it, this will
   * be `undefined`.
   *
   * If the version should be entirely omitted from the response (for example,
   * when sending preliminary headers when streaming), this will be `null`.
   */
  version: ExecutionVersion | null | undefined;
}
/**
 * A version of {@link HandlerResponse} where each function is safely
 * promisified and requires a reason for each access.
 *
 * This enables us to provide accurate errors for each access without having to
 * wrap every access in a try/catch.
 */
type ActionHandlerResponseWithErrors = { [K in keyof HandlerResponse]: NonNullable<HandlerResponse[K]> extends ((...args: infer Args) => infer R) ? R extends MaybePromise<infer PR> ? (errMessage: string, ...args: Args) => Promise<PR> : (errMessage: string, ...args: Args) => Promise<R> : HandlerResponse[K] };
/**
 * A version of {@link ActionHandlerResponseWithErrors} that includes helper
 * functions that provide sensible defaults on top of the direct access given
 * from the bare response.
 */
interface HandlerResponseWithErrors extends ActionHandlerResponseWithErrors {
  /**
   * Fetch a query string value from the request. If no `querystring` action has
   * been provided by the `serve()` handler, this will fall back to using the
   * provided URL present in the request to parse the query string from instead.
   */
  queryStringWithDefaults: (reason: string, key: string) => Promise<string | undefined>;
}
//#endregion
export { ActionResponse, InngestCommHandler, ServeHandlerOptions, SyncAdapterOptions, SyncHandlerOptions };
//# sourceMappingURL=InngestCommHandler.d.cts.map