Skip to content

Commit 194c94b

Browse files
unnoqCopilot
andauthored
feat(ratelimit): Cloudflare Worker Ratelimit Adapter (#1212)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Cloudflare as a new ratelimit adapter option with example usage. * **Documentation** * Updated adapter docs to include the Cloudflare ratelimit adapter alongside existing adapters. * **Tests** * Added unit tests covering the Cloudflare ratelimit adapter's behavior and delegation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 9540489 commit 194c94b

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

apps/content/docs/helpers/ratelimit.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const limiter = new RedisRatelimiter({
7272
You can use any Redis client that supports Lua script evaluation by providing an `eval` function.
7373
:::
7474

75-
### Upstash Adapter
75+
### Upstash Ratelimit Adapter
7676

7777
Adapter for [@upstash/ratelimit](https://www.npmjs.com/package/@upstash/ratelimit), optimized for serverless environments like Vercel Edge and Cloudflare Workers.
7878

@@ -103,6 +103,22 @@ const limiter = new UpstashRatelimiter(ratelimit, {
103103

104104
:::
105105

106+
### Cloudflare Ratelimit Adapter
107+
108+
Adapter for [Cloudflare Workers Ratelimit](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/).
109+
110+
```ts
111+
import { CloudflareRatelimiter } from '@orpc/experimental-ratelimit/cloudflare-ratelimit'
112+
113+
export default {
114+
async fetch(request, env) {
115+
const limiter = new CloudflareRatelimiter(env.MY_RATE_LIMITER)
116+
117+
return new Response(`Hello World!`)
118+
}
119+
}
120+
```
121+
106122
## Blocking Mode
107123

108124
Some adapters support blocking mode, which waits for the rate limit to reset instead of immediately rejecting requests.

packages/ratelimit/package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,20 @@
3434
"types": "./dist/adapters/upstash-ratelimit.d.mts",
3535
"import": "./dist/adapters/upstash-ratelimit.mjs",
3636
"default": "./dist/adapters/upstash-ratelimit.mjs"
37+
},
38+
"./cloudflare-ratelimit": {
39+
"types": "./dist/adapters/cloudflare-ratelimit.d.mts",
40+
"import": "./dist/adapters/cloudflare-ratelimit.mjs",
41+
"default": "./dist/adapters/cloudflare-ratelimit.mjs"
3742
}
3843
}
3944
},
4045
"exports": {
4146
".": "./src/index.ts",
4247
"./memory": "./src/adapters/memory.ts",
4348
"./redis": "./src/adapters/redis.ts",
44-
"./upstash-ratelimit": "./src/adapters/upstash-ratelimit.ts"
49+
"./upstash-ratelimit": "./src/adapters/upstash-ratelimit.ts",
50+
"./cloudflare-ratelimit": "./src/adapters/cloudflare-ratelimit.ts"
4551
},
4652
"files": [
4753
"dist"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { CloudflareRatelimiter } from './cloudflare-ratelimit'
2+
3+
it('cloudflareRatelimiter', async () => {
4+
const ratelimit = {
5+
limit: vi.fn(() => Promise.resolve({ success: true })),
6+
}
7+
8+
const ratelimiter = new CloudflareRatelimiter(ratelimit)
9+
10+
const result = ratelimiter.limit('test-key')
11+
12+
expect(ratelimit.limit).toHaveBeenCalledTimes(1)
13+
expect(ratelimit.limit).toHaveBeenCalledWith({ key: 'test-key' })
14+
expect(result).toBe(ratelimit.limit.mock.results[0]!.value)
15+
16+
expect(await result).toEqual({ success: true })
17+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { Ratelimiter, RatelimiterLimitResult } from '../types'
2+
3+
export class CloudflareRatelimiter implements Ratelimiter {
4+
constructor(
5+
private readonly ratelimit: {
6+
limit: (options: { key: string }) => Promise<RatelimiterLimitResult>
7+
},
8+
) {}
9+
10+
limit(key: string): Promise<RatelimiterLimitResult> {
11+
return this.ratelimit.limit({ key })
12+
}
13+
}

0 commit comments

Comments
 (0)