diff --git a/src/frontend/src/hooks/useRateLimiter.ts b/src/frontend/src/hooks/useRateLimiter.ts new file mode 100644 index 00000000..82ff8cda --- /dev/null +++ b/src/frontend/src/hooks/useRateLimiter.ts @@ -0,0 +1,37 @@ +import { useCallback, useRef } from 'react' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type RateLimiterProps any> = { + callback: T + maxCalls: number + windowMs: number +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default function useRateLimiter any>({ + callback, + maxCalls = 5, + windowMs = 1000, +}: RateLimiterProps) { + const callsCountRef = useRef(0) + const resetTimeoutRef = useRef(undefined) + + const rateLimitedFn = useCallback( + (...args: Parameters) => { + if (callsCountRef.current < maxCalls) { + callsCountRef.current += 1 + if (callsCountRef.current === 1) { + resetTimeoutRef.current = setTimeout(() => { + callsCountRef.current = 0 + resetTimeoutRef.current = undefined + }, windowMs) + } + return callback(...args) + } else { + return null + } + }, + [callback, maxCalls, windowMs] + ) + return rateLimitedFn +}