import { AnyAsyncFunction, AnyFunction, CallExpr, Expr, FunctionLike } from "@functionless/ast";
import { aws_events_targets, aws_lambda } from "aws-cdk-lib";
import { IDestination } from "aws-cdk-lib/aws-lambda";
import type { Context } from "aws-lambda";
import { Construct } from "constructs";
import esbuild from "esbuild";
import { ApiGatewayVtlIntegration } from "./api";
import { AppSyncVtlIntegration } from "./appsync";
import { ASL, ASLGraph } from "./asl";
import { IEventBus, Event, EventBusTargetIntegration, Rule } from "./event-bridge";
import { NativePreWarmContext, PrewarmProps } from "./function-prewarm";
import { Integration } from "./integration";
export declare function isFunction<Payload = any, Output = any>(a: any): a is IFunction<Payload, Output>;
export declare type AnyLambda = Function<any, any>;
export interface FunctionEventBusTargetProps extends Omit<aws_events_targets.LambdaFunctionProps, "event"> {
}
export declare type FunctionClosure<in Payload, out Output> = (payload: Payload, context: Context) => Promise<Output>;
/**
 * Returns the payload type on the {@link IFunction}.
 */
export declare type FunctionPayloadType<Func extends IFunction<any, any>> = [
    Func
] extends [IFunction<infer P, any>] ? P : never;
/**
 * Returns the output type on the {@link IFunction}.
 */
export declare type FunctionOutputType<Func extends IFunction<any, any>> = [
    Func
] extends [IFunction<any, infer O>] ? O : never;
declare type FunctionAsyncOnFailureDestination<Payload> = aws_lambda.FunctionProps["onFailure"] | IEventBus<AsyncResponseFailureEvent<Payload>> | IFunction<AsyncResponseFailure<Payload>, any>;
declare type FunctionAsyncOnSuccessDestination<Payload, Output> = aws_lambda.FunctionProps["onSuccess"] | IEventBus<AsyncResponseSuccessEvent<Payload, Output>> | IFunction<AsyncResponseSuccess<Payload, Output>, any>;
/**
 * Wrapper around {@link aws_lambda.EventInvokeConfigOptions} which allows users to provide Functionless
 * {@link EventBus} and {@link Function} for the onSuccess and onFailure async event destinations.
 */
export interface EventInvokeConfigOptions<Payload, Output> extends Omit<aws_lambda.EventInvokeConfigOptions, "onSuccess" | "onFailure"> {
    onSuccess?: FunctionAsyncOnSuccessDestination<Payload, Output>;
    onFailure?: FunctionAsyncOnFailureDestination<Payload>;
}
/**
 * @typeParam Payload - The super-set payload type of the function.
 * @typeParam Output - The output type of the function.
 * @typeParam OutPayload - The covariant type of {@link Payload} used when the payload is output.
 *                         For example when the Payload is sent to a {@link Function} or {@link EventBus}
 *                         from onSuccess or onFailure event sources. This type parameter should be left
 *                         empty to be inferred. ex: `Function<Payload1, Output1 | Output2>`.
 */
export interface IFunction<in Payload, Output> extends Integration<"Function", ConditionalFunction<Payload, Output>> {
    readonly functionlessKind: typeof Function.FunctionlessType;
    readonly kind: typeof Function.FunctionlessType;
    readonly resource: aws_lambda.IFunction;
    (...args: Parameters<ConditionalFunction<Payload, Output>>): ReturnType<ConditionalFunction<Payload, Output>>;
    /**
     * Event Source for the {@link Function} onSuccess async invocation destination.
     *
     * For Lambda, the onSuccess destination is not enabled by default.
     * It must first be configured via either the {@link Function} constructor
     * or by using {@link IFunction.enableAsyncInvoke} and that destination must match the bus provided here.
     *
     * ```ts
     * const bus = new EventBus(stack, 'bus');
     * new Function(stack, 'func', { onSuccess: bus }, async () => {});
     * ```
     *
     * or
     *
     * ```ts
     * const bus = new EventBus(stack, 'bus');
     * const func = new Function(stack, 'func', async () => {});
     * // if onSuccess or onFailure is already set, this will fail.
     * func.enableAsyncInvoke({ onSuccess: bus });
     * ```
     *
     * @see https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations
     *
     * The rule returned will contain the logic:
     *
     * ```ts
     * when(id, event => event.source === "lambda"
     *    && event["detail-type"] === "Lambda Function Invocation Result - Success"
     *      && event.resources.includes(this.resource.functionArn))
     * ```
     */
    onSuccess<OutPayload extends Payload>(bus: IEventBus<AsyncResponseSuccessEvent<OutPayload, Output>>, id: string): Rule<AsyncResponseSuccessEvent<OutPayload, Output>>;
    /**
     * Event Source for the {@link Function} onFailure async invocation destination.
     *
     * The onFailure destination is not enabled by default.
     * It must first be configured via either the {@link Function} constructor
     * or by using {@link IFunction.enableAsyncInvoke} and that destination must match the bus provided here.
     *
     * ```ts
     * const bus = new EventBus(stack, 'bus');
     * new Function(stack, 'func', { onFailure: bus }, async () => {});
     * ```
     *
     * or
     *
     * ```ts
     * const bus = new EventBus(stack, 'bus');
     * const func = new Function(stack, 'func', async () => {});
     * // if onSuccess or onFailure is already set, this will fail.
     * func.enableAsyncInvoke({ onFailure: bus });
     * ```
     *
     * @see https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations
     *
     * The rule returned will contain the logic:
     *
     * ```ts
     * when(id, event => event.source === "lambda"
     *    && event["detail-type"] === "Lambda Function Invocation Result - Failure"
     *      && event.resources.includes(this.resource.functionArn))
     * ```
     */
    onFailure<OutPayload extends Payload>(bus: IEventBus<AsyncResponseFailureEvent<OutPayload>>, id: string): Rule<AsyncResponseFailureEvent<OutPayload>>;
    /**
     * Set the async invocation options on a function. Can be use to enable and set the onSuccess and onFailure destinations.
     *
     * Wraps {@link aws_lambda.IFunction.configureAsyncInvoke} provided by CDK to support Functionless resources directly.
     *
     * If onSuccess or onFailure were already set either through {@link FunctionProps} or {@link IFunction.enableAsyncInvoke}
     * This method will fail.
     */
    enableAsyncInvoke<OutPayload extends Payload>(config: EventInvokeConfigOptions<OutPayload, Output>): void;
    readonly eventBus: EventBusTargetIntegration<Payload, FunctionEventBusTargetProps | undefined>;
}
export interface AsyncResponseBase<P> {
    version: string;
    /**
     * ISO 8601
     */
    timestamp: string;
    requestPayload: P;
    responseContext: {
        statusCode: number;
        executedVersion: "$LATEST" | string;
        functionError: string;
    };
}
export declare type AsyncFunctionResponseEvent<P, O> = AsyncResponseSuccessEvent<P, O> | AsyncResponseFailureEvent<P>;
export interface AsyncResponseSuccess<P, O> extends AsyncResponseBase<P> {
    responsePayload: O;
    requestContext: {
        requestId: string;
        functionArn: string;
        condition: "Success";
        approximateInvokeCount: number;
    };
}
export interface AsyncResponseFailure<P> extends AsyncResponseBase<P> {
    requestContext: {
        requestId: string;
        functionArn: string;
        condition: "RetriesExhausted" | "EventAgeExceeded" | string;
        approximateInvokeCount: number;
    };
    responsePayload: {
        errorMessage: string;
        errorType: string;
        stackTrace: string[];
    };
}
export interface AsyncResponseSuccessEvent<P, O> extends Event<AsyncResponseSuccess<P, O>, "Lambda Function Invocation Result - Success", "lambda"> {
}
export interface AsyncResponseFailureEvent<P> extends Event<AsyncResponseFailure<P>, "Lambda Function Invocation Result - Failure", "lambda"> {
}
declare abstract class FunctionBase<in Payload, Out> implements IFunction<Payload, Out>, Integration<"Function", ConditionalFunction<Payload, Out>> {
    readonly resource: aws_lambda.IFunction;
    readonly kind: "Function";
    readonly native: NativeIntegration<ConditionalFunction<Payload, Out>>;
    readonly functionlessKind = "Function";
    static readonly FunctionlessType = "Function";
    readonly appSyncVtl: AppSyncVtlIntegration;
    readonly apiGWVtl: ApiGatewayVtlIntegration;
    readonly __functionBrand: ConditionalFunction<Payload, Out>;
    constructor(resource: aws_lambda.IFunction);
    asl(call: CallExpr, context: ASL): (import("./asl").Choice & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | (import("./asl").Fail & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        Next: string;
        End?: undefined;
    } & {
        Comment?: string | undefined;
        Parameters?: import("./asl").Parameters | undefined;
        ResultSelector?: import("./asl").Parameters | undefined;
        ResultPath?: string | null | undefined;
        Retry?: import("./asl").Retry[] | undefined;
        Catch?: import("./asl").Catch[] | undefined;
    } & {
        Type: "Map";
        Iterator: import("./asl").StateMachine<import("./asl").States>;
        ItemsPath?: string | undefined;
        ResultPath?: string | null | undefined;
        MaxConcurrency?: number | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        End: true;
        Next?: undefined;
    } & {
        Comment?: string | undefined;
        Parameters?: import("./asl").Parameters | undefined;
        ResultSelector?: import("./asl").Parameters | undefined;
        ResultPath?: string | null | undefined;
        Retry?: import("./asl").Retry[] | undefined;
        Catch?: import("./asl").Catch[] | undefined;
    } & {
        Type: "Map";
        Iterator: import("./asl").StateMachine<import("./asl").States>;
        ItemsPath?: string | undefined;
        ResultPath?: string | null | undefined;
        MaxConcurrency?: number | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        Next: string;
        End?: undefined;
    } & {
        Comment?: string | undefined;
        Parameters?: import("./asl").Parameters | undefined;
        ResultSelector?: import("./asl").Parameters | undefined;
        ResultPath?: string | null | undefined;
        Retry?: import("./asl").Retry[] | undefined;
        Catch?: import("./asl").Catch[] | undefined;
    } & {
        Type: "Parallel";
        Branches: import("./asl").StateMachine<import("./asl").States>[];
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        End: true;
        Next?: undefined;
    } & {
        Comment?: string | undefined;
        Parameters?: import("./asl").Parameters | undefined;
        ResultSelector?: import("./asl").Parameters | undefined;
        ResultPath?: string | null | undefined;
        Retry?: import("./asl").Retry[] | undefined;
        Catch?: import("./asl").Catch[] | undefined;
    } & {
        Type: "Parallel";
        Branches: import("./asl").StateMachine<import("./asl").States>[];
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        Next: string;
        End?: undefined;
    } & {
        Comment?: string | undefined;
        Type: "Pass";
        Result?: any;
        ResultPath?: string | null | undefined;
        Parameters?: import("./asl").Parameters | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        End: true;
        Next?: undefined;
    } & {
        Comment?: string | undefined;
        Type: "Pass";
        Result?: any;
        ResultPath?: string | null | undefined;
        Parameters?: import("./asl").Parameters | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | (import("./asl").Succeed & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        Next: string;
        End?: undefined;
    } & {
        Comment?: string | undefined;
        Parameters?: import("./asl").Parameters | undefined;
        ResultSelector?: import("./asl").Parameters | undefined;
        ResultPath?: string | null | undefined;
        Retry?: import("./asl").Retry[] | undefined;
        Catch?: import("./asl").Catch[] | undefined;
    } & {
        Type: "Task";
        Resource: string;
        TimeoutSeconds?: number | undefined;
        TimeoutSecondsPath?: string | undefined;
        HeartbeatSeconds?: number | undefined;
        HeartbeatSecondsPath?: string | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        End: true;
        Next?: undefined;
    } & {
        Comment?: string | undefined;
        Parameters?: import("./asl").Parameters | undefined;
        ResultSelector?: import("./asl").Parameters | undefined;
        ResultPath?: string | null | undefined;
        Retry?: import("./asl").Retry[] | undefined;
        Catch?: import("./asl").Catch[] | undefined;
    } & {
        Type: "Task";
        Resource: string;
        TimeoutSeconds?: number | undefined;
        TimeoutSecondsPath?: string | undefined;
        HeartbeatSeconds?: number | undefined;
        HeartbeatSecondsPath?: string | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        Next: string;
        End?: undefined;
    } & {
        Type: "Wait";
        Seconds?: number | undefined;
        Timestamp?: string | undefined;
        SecondsPath?: string | undefined;
        TimestampPath?: string | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ({
        Comment?: string | undefined;
        InputPath?: string | undefined;
        OutputPath?: string | undefined;
    } & {
        End: true;
        Next?: undefined;
    } & {
        Type: "Wait";
        Seconds?: number | undefined;
        Timestamp?: string | undefined;
        SecondsPath?: string | undefined;
        TimestampPath?: string | undefined;
    } & {
        node?: import("@functionless/ast").FunctionlessNode | undefined;
    } & {
        output: ASLGraph.Output;
    }) | ASLGraph.OutputSubState | ASLGraph.LiteralValue<ASLGraph.LiteralValueType> | ASLGraph.JsonPath | ASLGraph.ConditionOutput;
    protected static normalizeAsyncDestination<P, O>(destination: FunctionAsyncOnSuccessDestination<P, O> | FunctionAsyncOnFailureDestination<P>): IDestination | undefined;
    enableAsyncInvoke<OutPayload extends Payload>(config: EventInvokeConfigOptions<OutPayload, Out>): void;
    onSuccess<OutPayload extends Payload>(bus: IEventBus<AsyncResponseSuccessEvent<OutPayload, Out>>, id: string): Rule<AsyncResponseSuccessEvent<OutPayload, Out>>;
    onFailure<OutPayload extends Payload>(bus: IEventBus<AsyncResponseFailureEvent<OutPayload>>, id: string): Rule<AsyncResponseFailureEvent<OutPayload>>;
    readonly eventBus: EventBusTargetIntegration<Payload, FunctionEventBusTargetProps | undefined>;
}
interface FunctionBase<in Payload, Out> {
    (...args: Parameters<ConditionalFunction<Payload, Out>>): ReturnType<ConditionalFunction<Payload, Out>>;
}
export declare enum SerializerImpl {
    /**
     * The default serializer, uses the v8 inspector API to introspect closures.
     *
     * It is slow and has caveats such as not properly serializing stable references to variables.
     *
     * @see https://github.com/functionless/nodejs-closure-serializer
     */
    V1 = 0,
    /**
     * A new experimental serializer that makes use of Functionless's SWC AST
     * reflection library that decorates syntax for use at runtime.
     *
     * It has not been as well tested, but is fast, synchronous and has support for
     * stable references and other features.
     *
     * @see https://www.npmjs.com/package/@functionless/ast-reflection
     */
    V2 = 1,
    Default = 0
}
export interface FunctionProps<in P = any, O = any, OutP extends P = P> extends Omit<aws_lambda.FunctionProps, "code" | "handler" | "runtime" | "onSuccess" | "onFailure"> {
    /**
     * Whether to generate source maps for serialized closures and
     * to set --enableSourceMaps on NODE_OPTIONS environment variable.
     *
     * Only supported when using {@link SerializerImpl.V2}.
     *
     * @default true
     */
    sourceMaps?: boolean;
    /**
     * Which {@link SerializerImpl} to use when serializing closures.
     *
     * @default {@link SerializerImpl.V1}
     */
    serializer?: SerializerImpl;
    /**
     * Method which allows runtime computation of AWS client configuration.
     * ```ts
     * new Lambda(clientConfigRetriever('LAMBDA'))
     * ```
     *
     * @param clientName optionally return a different client config based on the {@link ClientName}.
     *
     */
    clientConfigRetriever?: PrewarmProps["clientConfigRetriever"];
    /**
     * The destination for failed invocations.
     *
     * Supports use of Functionless {@link IEventBus} or {@link IFunction}.
     *
     * ```ts
     * const bus = new EventBus<>
     * ```
     *
     * @default - no destination
     */
    onSuccess?: FunctionAsyncOnSuccessDestination<OutP, O>;
    /**
     * The destination for successful invocations.
     *
     * @default - no destination
     */
    onFailure?: FunctionAsyncOnFailureDestination<OutP>;
}
/**
 * A type-safe NodeJS Lambda Function generated from the closure provided.
 *
 * Can be called from within an {@link AppsyncResolver}.
 *
 * For example:
 * ```ts
 * const getPerson = new Function<string, Person>(stack, 'func', async () => {
 *  // get person logic
 * });
 *
 * new AppsyncResolver(() => {
 *   return getPerson("value");
 * })
 * ```
 *
 * Can wrap an existing {@link aws_lambda.Function}.
 *
 * ```ts
 * const getPerson = Function.fromFunction<string, Person>(
 *   new aws_lambda.Function(..)
 * );
 * ```
 */
export declare class Function<in Payload, Out = any, OutPayload extends Payload = Payload> extends FunctionBase<Payload, Out> {
    /**
     * Dangling promises which are processing Function handler code from the function serializer.
     * To correctly resolve these for CDK synthesis, either use `asyncSynth()` or use `cdk synth` in the CDK cli.
     * https://twitter.com/samgoodwin89/status/1516887131108438016?s=20&t=7GRGOQ1Bp0h_cPsJgFk3Ww
     */
    static readonly promises: Promise<void>[];
    /**
     * Wrap a {@link aws_lambda.Function} with Functionless.
     *
     * A wrapped function can be invoked, but the code is provided in the CDK Construct.
     */
    static fromFunction<Payload = any, Out = any>(func: aws_lambda.IFunction): ImportedFunction<Payload, Out>;
    /**
     * Create a lambda function using a native typescript closure.
     *
     * ```ts
     * new Function<{ val: string }, string>(this, 'myFunction', async (event) => event.val);
     * ```
     */
    constructor(scope: Construct, id: string, func: FunctionClosure<Payload, Out>);
    constructor(scope: Construct, id: string, props: FunctionProps<Payload, Out, OutPayload>, func: FunctionClosure<Payload, Out>);
}
export declare function inferIamPolicies(decl: FunctionLike<AnyFunction>, func: aws_lambda.IFunction): void;
export interface IntegrationInvocation {
    integration: Integration<any>;
    args: Expr[];
}
export declare function findAllIntegrations(decl: FunctionLike<AnyFunction>): IntegrationInvocation[];
/**
 * A {@link Function} which wraps a CDK function.
 *
 * An imported function can be invoked, but the code is provided in the CDK Construct.
 */
export declare class ImportedFunction<Payload, Out> extends FunctionBase<Payload, Out> {
}
declare type ConditionalFunction<Payload, Out> = [Payload] extends [undefined] ? (payload?: Payload) => Promise<Out> : (payload: Payload) => Promise<Out>;
interface CallbackLambdaCodeProps extends PrewarmProps {
}
/**
 * A special lambda code wrapper that serializes whatever closure it is given.
 *
 * Caveat: Relies on async functions which may not finish when using CDK's app.synth()
 *
 * Ensure the generate function's promise is completed using something like Lambda.promises and the `asyncSynth` function.
 *
 * Use:
 * * Initialize the {@link CallbackLambdaCode} `const code = new CallbackLambdaCode()`
 * * First bind the code to a Function `new aws_lambda.Function(..., { code })`
 * * Then call generate `const promise = code.generate(integrations)`
 *
 */
export declare class CallbackLambdaCode extends aws_lambda.Code {
    private func;
    private props;
    private scope;
    constructor(func: AnyAsyncFunction, props: CallbackLambdaCodeProps);
    bind(scope: Construct): aws_lambda.CodeConfig;
    /**
     * Thanks to cloudy for the help getting this to work.
     * https://github.com/skyrpex/cloudy/blob/main/packages/cdk/src/aws-lambda/callback-function.ts#L518-L540
     * https://twitter.com/samgoodwin89/status/1516887131108438016?s=20&t=7GRGOQ1Bp0h_cPsJgFk3Ww
     */
    generate(integrationPrewarms: NativeIntegration<AnyFunction>["preWarm"][], serializerImpl: SerializerImpl, sourceMaps: boolean): Promise<void>;
}
/**
 * Interface to consume to add an Integration to Native Lambda Functions.
 *
 * ```ts
 * new Function(this, 'func', () => {
 *    mySpecialIntegration()
 * })
 *
 * const mySpecialIntegration = makeIntegration<() => void>({
 *    native: {...} // an instance of NativeIntegration
 * })
 * ```
 */
export interface NativeIntegration<Func extends AnyFunction> {
    /**
     * Called by any {@link Function} that will invoke this integration during CDK Synthesis.
     * Add permissions, create connecting resources, validate.
     *
     * @param context - The function invoking this function.
     * @param args - The functionless encoded AST form of the arguments passed to the integration.
     */
    bind: (context: aws_lambda.IFunction, args: Expr[]) => void;
    /**
     * @param args The arguments passed to the integration function by the user.
     * @param preWarmContext contains singleton instances of client and other objects initialized outside of the native
     *                       function handler.
     */
    call: (args: Parameters<Func>, preWarmContext: NativePreWarmContext) => ReturnType<Func>;
    /**
     * Method called outside of the handler to initialize things like the PreWarmContext
     */
    preWarm?: (preWarmContext: NativePreWarmContext) => void;
}
interface TokenContext {
    token: string;
    env: `env__functionless${string}`;
}
/**
 * Serializes a function to a string, extracting tokens and replacing some objects with a simpler form.
 */
export declare function serialize(func: AnyAsyncFunction, integrationPrewarms: NativeIntegration<AnyFunction>["preWarm"][], serializerImpl?: SerializerImpl, props?: PrewarmProps): Promise<[string, TokenContext[]]>;
/**
 * Bundles a serialized function with esbuild.
 */
export declare function bundle(text: string, sourceMap?: boolean): Promise<esbuild.OutputFile>;
export declare const deploymentOnlyModule = true;
export {};
//# sourceMappingURL=function.d.ts.map