import type { GraphQLField, GraphQLNamedOutputType } from 'graphql';
import type { Plugin } from '@envelop/core';
import { getGraphQLRateLimiter } from './get-graphql-rate-limiter.cjs';
import type { FormatErrorInput, GraphQLRateLimitConfig, GraphQLRateLimitDirectiveArgs, Identity, Options } from './types.cjs';
export { type FormatErrorInput, type GraphQLRateLimitConfig, type GraphQLRateLimitDirectiveArgs, type Identity, type Options, };
/**
 * Returns a string that uniquely identifies the caller for rate limiting.
 *
 * Receives the execution context and the resolved field argument values. Note that `args` is
 * only populated when the function is invoked via `configByField`. When used as the plugin-level
 * `identifyFn` for directive-based rate limiting, `args` will be an empty object.
 */
export type IdentifyFn<ContextType = unknown> = (context: ContextType, args: Record<string, unknown>) => string;
interface RateLimitExecutionParams<ContextType = unknown> {
    root: unknown;
    args: Record<string, unknown>;
    context: ContextType;
    type: GraphQLNamedOutputType;
    field: GraphQLField<any, any>;
}
export type MessageInterpolator<ContextType = unknown> = (message: string, identifier: string, params: RateLimitExecutionParams<ContextType>) => string;
export declare const DIRECTIVE_SDL = "\n  directive @rateLimit(\n    max: Int\n    window: String\n    message: String\n    identityArgs: [String]\n    arrayLengthField: String\n    readOnly: Boolean\n    uncountRejected: Boolean\n  ) on FIELD_DEFINITION\n";
export type RateLimitDirectiveArgs = {
    max?: number;
    window?: string;
    message?: string;
    /**
     * Field argument names whose values are included in the rate limit key, creating a separate
     * bucket per unique combination of values. Equivalent to `@rateLimit(identityArgs: [...])`.
     *
     * @example
     * identityArgs: ['id']  // one bucket per unique id argument value
     */
    identityArgs?: string[];
    arrayLengthField?: string;
    readOnly?: boolean;
    uncountRejected?: boolean;
};
export type RateLimiterPluginOptions = {
    identifyFn: IdentifyFn;
    rateLimitDirectiveName?: 'rateLimit' | string;
    transformError?: (message: string) => Error;
    onRateLimitError?: (event: {
        error: string;
        identifier: string;
    } & RateLimitExecutionParams) => void;
    interpolateMessage?: MessageInterpolator;
    configByField?: ConfigByField[];
} & Omit<GraphQLRateLimitConfig, 'identifyContext'>;
export interface ConfigByField extends RateLimitDirectiveArgs {
    type: string;
    field: string;
    /**
     * Override the identity function for this specific field. Takes precedence over the
     * plugin-level `identifyFn`.
     *
     * Unlike the plugin-level `identifyFn`, this is always called with the resolved field
     * argument values, making it suitable for unauthenticated rate limiting keyed on an argument.
     *
     * @example
     * identifyFn: (ctx, args) => String(args.id)
     */
    identifyFn?: IdentifyFn;
    /**
     * A template string that builds the rate limit identity key using `{args.argName}` or
     * `{context.propName}` dot-path interpolation. Takes precedence over `identifyFn` when set.
     *
     * Use this as a concise alternative to `identifyFn` when the identity is a single path.
     *
     * @example
     * identifier: "{args.id}"      // one bucket per argument value
     * identifier: "{context.ip}"   // one bucket per ip, no auth required
     */
    identifier?: string;
}
export declare const defaultInterpolateMessageFn: MessageInterpolator;
interface RateLimiterContext {
    rateLimiterFn: ReturnType<typeof getGraphQLRateLimiter>;
}
export declare const useRateLimiter: (options: RateLimiterPluginOptions) => Plugin<RateLimiterContext>;
export { InMemoryStore } from './in-memory-store.cjs';
export { RedisStore } from './redis-store.cjs';
export { Store } from './store.cjs';
