@envelop/rate-limiter
Version:
84 lines (83 loc) • 3.94 kB
text/typescript
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';