Files
NextEdu/src/shared/lib/rate-limit/index.ts
SpecialX 0e63c24ed9
Some checks failed
CI / scheduled-backup (push) Has been skipped
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled
feat(shared,tests): add error boundaries, lib utils, i18n messages, and integration tests
shared:

- Add class-filter, error-state, route-error, section-error-boundary, widget-boundary components

- Add ui/alert component

- Add constants directory

- Add breached-password, export-utils, permission-bitmap, rate-limit, resolve-action-error, route-permissions, route-resolver, type-guards lib

- Add i18n messages (en, zh-CN) for invitation-codes, parent, questions, rbac

tests:

- Add integration tests for elective

- Add tests/setup/empty-stub

scripts:

- Add update-md.cjs, tmp_append_en.ps1, tmp_merge_en.ps1 utilities
2026-07-03 10:26:38 +08:00

72 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 速率限制器门面audit-P1-6
*
* 公共 API 与原 `rate-limit.ts` 单文件保持一致,差异:
* - `rateLimit()` 与 `resetRateLimit()` 改为 `Promise` 返回,以支持异步后端
* - 内部根据 `RATE_LIMIT_DRIVER` 环境变量选择实现:
* - `memory`(默认):单实例内存滑动窗口
* - `redis`:基于 @upstash/ratelimit + @upstash/redis 的分布式实现
* - 调用方需 `await rateLimit(...)` / `await resetRateLimit(...)`
*
* `rateLimitKey` / `RATE_LIMIT_RULES` / `rateLimitHeaders` 保持同步纯函数。
*/
import { env } from "@/env.mjs"
import type { RateLimiter, RateLimitParams, RateLimitResult } from "./types"
export type { RateLimiter, RateLimitParams, RateLimitResult } from "./types"
export { RATE_LIMIT_RULES, rateLimitHeaders, rateLimitKey } from "./rules"
import { MemoryRateLimiter } from "./memory-limiter"
import { RedisRateLimiter } from "./redis-limiter"
/**
* 单例限流器实例(按 env 选择实现,进程级复用)。
*
* RedisRateLimiter 类本身在 import 时不会加载 @upstash/* 依赖——
* 重依赖通过类方法内的 `await import(...)` 懒加载,
* 仅当 `RATE_LIMIT_DRIVER=redis` 且实际调用 `limit()` 时才加载。
*/
let singleton: RateLimiter | null = null
/**
* 获取当前进程的限流器实例。
*
* - 默认返回内存实现
* - 当 `RATE_LIMIT_DRIVER=redis` 时返回 Redis 实现
* - Redis 实现懒加载所需依赖,未安装 @upstash/ratelimit/redis 时首次调用抛错
*/
export function getRateLimiter(): RateLimiter {
if (singleton) return singleton
if (env.RATE_LIMIT_DRIVER === "redis") {
singleton = new RedisRateLimiter()
} else {
singleton = new MemoryRateLimiter()
}
return singleton
}
/**
* 检查请求是否应被允许。
*
* 无论成功失败均累加计数(便于失败次数累计锁定)。
*
* **变更**:返回 `Promise<RateLimitResult>`,调用方需 `await`。
*/
export function rateLimit(params: RateLimitParams): Promise<RateLimitResult> {
return getRateLimiter().limit(params)
}
/**
* 重置指定 key 的计数。
*
* 用于成功登录后清除失败计数等场景。
*
* **变更**:返回 `Promise<void>`,调用方需 `await`。
*/
export function resetRateLimit(key: string): Promise<void> {
return getRateLimiter().reset(key)
}