File size: 1,723 Bytes
e218aaf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { db } from '@/lib/db';

export async function rateLimit(
  key: string,
  maxRequests: number,
  windowMs: number
): Promise<{ allowed: boolean; retryAfterMs: number }> {
  const now = new Date();

  try {
    const record = await db.rateLimit.findUnique({
      where: { key },
    });

    if (!record) {
      await db.rateLimit.create({
        data: {
          key,
          count: 1,
          resetAt: new Date(now.getTime() + windowMs),
        },
      });
      return { allowed: true, retryAfterMs: 0 };
    }

    if (now >= record.resetAt) {
      // Window expired — reset
      const updated = await db.rateLimit.update({
        where: { key },
        data: {
          count: 1,
          resetAt: new Date(now.getTime() + windowMs),
        },
      });
      return { allowed: true, retryAfterMs: 0 };
    }

    if (record.count >= maxRequests) {
      const retryAfterMs = record.resetAt.getTime() - now.getTime();
      return { allowed: false, retryAfterMs };
    }

    await db.rateLimit.update({
      where: { key },
      data: { count: { increment: 1 } },
    });

    return { allowed: true, retryAfterMs: 0 };
  } catch {
    // On DB error, allow the request through (fail-open)
    return { allowed: true, retryAfterMs: 0 };
  }
}

// Pre-configured rate limiters
export const authRateLimit = (key: string) =>
  rateLimit(key, 5, 60_000); // 5 requests per minute

export const uploadRateLimit = (key: string) =>
  rateLimit(key, 20, 60_000); // 20 requests per minute

export const chatRateLimit = (key: string) =>
  rateLimit(key, 20, 60_000); // 20 requests per minute

export const generalRateLimit = (key: string) =>
  rateLimit(key, 60, 60_000); // 60 requests per minute