import { AnyFunction, AwaitExpr, CallExpr, FunctionlessNode, ReferenceExpr } from "@functionless/ast";
import { ApiGatewayVtlIntegration } from "./api";
import { AppSyncVtlIntegration } from "./appsync";
import { ASL, ASLGraph } from "./asl";
import { EventBus, EventBusTargetIntegration } from "./event-bridge";
import { Function, NativeIntegration } from "./function";
import { VTL } from "./vtl";
export declare const isIntegration: <I extends Integration<string, AnyFunction>>(i: any) => i is I;
export interface IntegrationCallExpr extends CallExpr {
}
export declare function isIntegrationCallExpr(node: FunctionlessNode): node is IntegrationCallExpr;
export declare type IntegrationCallPattern = CallExpr | (AwaitExpr & {
    expr: CallExpr;
});
export declare function isIntegrationCallPattern(node: FunctionlessNode): node is IntegrationCallPattern;
/**
 * Give the possible ways to define an integration, return just the call(ref) of the integration.
 */
export declare function getIntegrationExprFromIntegrationCallPattern(pattern: IntegrationCallPattern): IntegrationCallExpr | undefined;
export declare const INTEGRATION_TYPE_KEYS: ("appSyncVtl" | "apiGWVtl" | "asl" | "eventBus" | "native")[];
/**
 * All integration methods supported by functionless.
 */
export interface IntegrationMethods<F extends AnyFunction> {
    /**
     * Integrate with AppSync VTL applications.
     * @private
     */
    appSyncVtl: AppSyncVtlIntegration;
    /**
     * Integrate with API Gateway VTL applications.
     * @private
     */
    apiGWVtl: ApiGatewayVtlIntegration;
    /**
     * Integrate with ASL applications like StepFunctions.
     *
     * TODO: Update to use an interface https://github.com/functionless/functionless/issues/197
     *
     * @private
     */
    asl: (call: CallExpr, context: ASL) => ASLGraph.NodeResults;
    eventBus: EventBusTargetIntegration<any, any>;
    /**
     * Native javascript code integrations that execute at runtime like Lambda.
     */
    native: NativeIntegration<F>;
}
/**
 * Integration types supported by Functionless.
 *
 * Add an integration by creating any object that has a property named "kind" and either implements the
 * {@link Integration} interface or has methods that implement it (or both).
 *
 * Example showing both strategies:
 *
 * ```ts
 * export class Function implements {@link Integration} {
 *    readonly kind = "Function",
 *
 *    // Integration Handler for ASL
 *    public asl(call, context) {
 *       // return Step Function task.
 *    }
 *
 *    // Example class method - some wrapper function that generates special ASL tasks when using a Function.
 *    public specialPayload = makeIntegration<() => string>({
 *        kind: "Function.default",
 *        asl: (call, context) => {
 *            // return step function task
 *        }
 *    });
 * }
 *
 * // an interface to provide the actual callable methods to users
 * export interface Function {
 *    // call me to send a string payload
 *    (payload: String) => string
 * }
 *
 * // use
 *
 * const func1 = new Function(...);
 * // uses the ASL
 * new StepFunction(..., async () => {
 *    await func1("some string");
 *    // Calling our special method in a step function closure
 *    await func1.specialPayload();
 * })
 * ```
 *
 * If an integration does not support an integration type, leave the function undefined or throw an error.
 *
 * Implement the unhandledContext function to customize the error message for unsupported contexts.
 * Otherwise the error will be: `${this.name} is not supported by context ${context.kindStr}.`
 */
export interface Integration<K extends string = string, F extends AnyFunction = AnyFunction> extends Partial<IntegrationMethods<F>> {
    /**
     * Brand the Function, F, into this type so that sub-typing rules apply to the function signature.
     */
    __functionBrand: F;
    /**
     * Integration Handler kind - for example StepFunction.describeExecution
     */
    readonly kind: K;
    /**
     * Optional method that allows overriding the {@link Error} thrown when a integration is not supported by a handler.
     * @param kind - The Kind of the integration.
     * @param contextKind - the Kind of the context attempting to use the integration.
     */
    readonly unhandledContext?: (kind: string, contextKind: CallContext["kind"]) => Error;
}
/**
 * Alias that removes computed inputs from the integration interface
 */
export declare type IntegrationInput<K extends string = string, F extends AnyFunction = AnyFunction> = Omit<Integration<K, F>, "__functionBrand">;
/**
 * Internal wrapper class for Integration handlers that provides default error handling for unsupported integrations.
 *
 * Functionless wraps Integration at runtime with this class.
 * @private
 */
export declare class IntegrationImpl<F extends AnyFunction = AnyFunction> implements IntegrationMethods<F> {
    readonly integration: Integration;
    readonly kind: string;
    constructor(integration: Integration);
    private assertIntegrationDefined;
    get appSyncVtl(): AppSyncVtlIntegration;
    get apiGWVtl(): ApiGatewayVtlIntegration;
    asl(call: CallExpr, context: ASL): ASLGraph.NodeResults;
    get eventBus(): EventBusTargetIntegration<any, any>;
    get native(): NativeIntegration<F>;
}
export declare type IntegrationCall<K extends string, F extends AnyFunction> = {
    FunctionlessType: K;
    kind: K;
    __functionBrand: F;
} & F;
/**
 * Helper method which masks an {@link Integration} object as a function of any form.
 *
 * ```ts
 * export namespace MyIntegrations {
 *    export const callMe = makeIntegration<(payload: string) => void>({
 *       asl: (call, context) => { ... }
 *    })
 * }
 * ```
 *
 * Creates an integration object at callMe, which is callable by a user.
 *
 * ```ts
 * MyIntegrations.callMe("some string");
 * ```
 *
 * @private
 */
export declare function makeIntegration<K extends string, F extends AnyFunction>(integration: IntegrationInput<K, F>): IntegrationCall<K, F>;
export declare type CallContext = ASL | VTL | Function<any, any> | EventBus<any>;
export declare function findDeepIntegrations(ast: FunctionlessNode): CallExpr<ReferenceExpr>[];
/**
 * A bottom-up algorithm that determines the ONLY {@link Integration} value that the {@link node}
 * will resolve to at runtime.
 *
 * If the {@link node} resolves to 0 or more than 1 {@link Integration} then `undefined` is returned.
 *
 * **Note**: This function is an intermediate helper until we migrate the interpreters to be more general
 * (likely by migrating to top-down algorithms, see https://github.com/functionless/functionless/issues/374#issuecomment-1203313604)
 *
 * @param node the node to resolve the {@link Integration} of.
 * @returns the ONLY {@link Integration} that {@link node} can resolve to, otherwise `undefined`.
 */
export declare function tryFindIntegration(node: FunctionlessNode): Integration | undefined;
/**
 * A bottom-up algorithm that determines all of the possible {@link Integration}s that a {@link node}
 * may resolve to at runtime.
 *
 * ```ts
 * declare const table1;
 * declare const table2;
 *
 * const tables = [table1, table2];
 *
 * const a = table1;
 *    // ^ [table1]
 *
 * for (const a of tables) {
 *   const b = a;
 *          // ^ [table1, table2]
 *
 *   const { appsync: { getItem } } = a;
 *                     // ^ [ table1.appsync.getItem, table2.appsync.getItem ]
 * }
 *
 * const a = tables[0];
 *          // ^ [table1]
 *
 * const { appsync: { getItem } } = table[0];
 *                   // ^ [ table1.appsync.getItem ]
 *
 * const { appsync: { getItem = table1.appsync.getItem } } = table[2];
 *                   // ^ [ table1.appsync.getItem ] (because of initializer)
 * ```
 *
 * @param node the node to resolve the possible {@link Integration}s of.
 * @returns a list of all the {@link Integration}s that the {@link node} could evaluate to.
 */
export declare function tryFindIntegrations(node: FunctionlessNode): Integration[];
/**
 * Resolve all of the possible values that {@link node} may resolve to at runtime.
 *
 * @param node
 * @param defaultValue default value to use if the value cannot be resolved (set by default initializers in BindingElement)
 * @returns an array of all the values the {@link node} resolves to.
 */
export declare function tryResolveReferences(node: FunctionlessNode | undefined, defaultValue?: FunctionlessNode): any[];
export declare const deploymentOnlyModule = true;
//# sourceMappingURL=integration.d.ts.map