Remove unused GraphQL throttler plugin and graphql-rate-limit dependency (#17785)
## Summary - Deletes `use-throttler.ts` — an envelop plugin that was never registered in the GraphQL config plugin chain (dead code since introduction) - Removes the `graphql-rate-limit` dependency from `package.json` (only consumer was the deleted file) API rate limiting continues to work via `ThrottlerService` in the query runner layer (for API key auth). Global coverage should be handled at the infrastructure level (Cloudflare). ## Test plan - [x] Confirmed no imports of `useThrottler`, `ThrottlerPluginOptions`, or `UnauthenticatedError` from this file exist anywhere in the codebase - [x] `graphql-rate-limit` has no other consumers Made with [Cursor](https://cursor.com) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -108,7 +108,6 @@
|
||||
"graphql": "16.8.1",
|
||||
"graphql-fields": "2.0.3",
|
||||
"graphql-middleware": "^6.1.35",
|
||||
"graphql-rate-limit": "3.3.0",
|
||||
"graphql-redis-subscriptions": "2.7.0",
|
||||
"graphql-scalars": "1.23.0",
|
||||
"graphql-subscriptions": "2.0.0",
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
import { type GraphQLResolveInfo } from 'graphql';
|
||||
import { getGraphQLRateLimiter } from 'graphql-rate-limit';
|
||||
import { type Plugin } from '@envelop/core';
|
||||
import { useOnResolve } from '@envelop/on-resolve';
|
||||
|
||||
import { type GraphQLContext } from 'src/engine/api/graphql/graphql-config/graphql-config.service';
|
||||
|
||||
export class UnauthenticatedError extends Error {}
|
||||
|
||||
export type IdentifyFn<ContextType = ThrottlerContext> = (
|
||||
context: ContextType,
|
||||
) => string;
|
||||
|
||||
export type ThrottlerPluginOptions = {
|
||||
identifyFn: IdentifyFn;
|
||||
ttl?: number;
|
||||
limit?: number;
|
||||
transformError?: (message: string) => Error;
|
||||
onThrottlerError?: (event: {
|
||||
error: string;
|
||||
identifier: string;
|
||||
context: unknown;
|
||||
info: GraphQLResolveInfo;
|
||||
}) => void;
|
||||
};
|
||||
|
||||
interface ThrottlerContext extends GraphQLContext {
|
||||
rateLimiterFn: ReturnType<typeof getGraphQLRateLimiter>;
|
||||
}
|
||||
|
||||
export const useThrottler = (
|
||||
options: ThrottlerPluginOptions,
|
||||
): Plugin<ThrottlerContext> => {
|
||||
const rateLimiterFn = getGraphQLRateLimiter({
|
||||
identifyContext: options.identifyFn,
|
||||
});
|
||||
|
||||
return {
|
||||
onPluginInit({ addPlugin }) {
|
||||
addPlugin(
|
||||
useOnResolve(async ({ args, root, context, info }) => {
|
||||
if (options.limit && options.ttl) {
|
||||
if (root !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = options.identifyFn(context);
|
||||
|
||||
const errorMessage = await context.rateLimiterFn(
|
||||
{ parent: root, args, context, info },
|
||||
{
|
||||
max: options?.limit,
|
||||
window: `${options?.ttl}s`,
|
||||
message: interpolate('Too many requests.', {
|
||||
id,
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
if (errorMessage) {
|
||||
if (options.onThrottlerError) {
|
||||
options.onThrottlerError({
|
||||
error: errorMessage,
|
||||
identifier: id,
|
||||
context,
|
||||
info,
|
||||
});
|
||||
}
|
||||
|
||||
if (options.transformError) {
|
||||
throw options.transformError(errorMessage);
|
||||
}
|
||||
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
async onContextBuilding({ extendContext }) {
|
||||
extendContext({
|
||||
rateLimiterFn,
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
function interpolate(message: string, args: { [key: string]: string }) {
|
||||
return message.replace(/\{{([^)]*)\}}/g, (_, key) => args[key.trim()]);
|
||||
}
|
||||
Reference in New Issue
Block a user