11import { env } from '@/lib/core/config/env'
2+ import { isBillingEnabled } from '@/lib/core/config/feature-flags'
23import type { CoreTriggerType } from '@/stores/logs/filters/types'
34import type { TokenBucketConfig } from './storage'
45
56export type TriggerType = CoreTriggerType | 'form' | 'api-endpoint'
67
78export type RateLimitCounterType = 'sync' | 'async' | 'api-endpoint'
89
10+ type RateLimitConfigKey = 'sync' | 'async' | 'apiEndpoint'
11+
912export type SubscriptionPlan = 'free' | 'pro' | 'team' | 'enterprise'
1013
1114export interface RateLimitConfig {
@@ -18,6 +21,17 @@ export const RATE_LIMIT_WINDOW_MS = Number.parseInt(env.RATE_LIMIT_WINDOW_MS) ||
1821
1922export const MANUAL_EXECUTION_LIMIT = Number . parseInt ( env . MANUAL_EXECUTION_LIMIT ) || 999999
2023
24+ const DEFAULT_RATE_LIMITS = {
25+ free : { sync : 50 , async : 200 , apiEndpoint : 30 } ,
26+ pro : { sync : 150 , async : 1000 , apiEndpoint : 100 } ,
27+ team : { sync : 300 , async : 2500 , apiEndpoint : 200 } ,
28+ enterprise : { sync : 600 , async : 5000 , apiEndpoint : 500 } ,
29+ } as const
30+
31+ function toConfigKey ( type : RateLimitCounterType ) : RateLimitConfigKey {
32+ return type === 'api-endpoint' ? 'apiEndpoint' : type
33+ }
34+
2135function createBucketConfig ( ratePerMinute : number , burstMultiplier = 2 ) : TokenBucketConfig {
2236 return {
2337 maxTokens : ratePerMinute * burstMultiplier ,
@@ -26,29 +40,64 @@ function createBucketConfig(ratePerMinute: number, burstMultiplier = 2): TokenBu
2640 }
2741}
2842
43+ function getRateLimitForPlan ( plan : SubscriptionPlan , type : RateLimitConfigKey ) : TokenBucketConfig {
44+ const envVarMap : Record < SubscriptionPlan , Record < RateLimitConfigKey , string | undefined > > = {
45+ free : {
46+ sync : env . RATE_LIMIT_FREE_SYNC ,
47+ async : env . RATE_LIMIT_FREE_ASYNC ,
48+ apiEndpoint : undefined ,
49+ } ,
50+ pro : { sync : env . RATE_LIMIT_PRO_SYNC , async : env . RATE_LIMIT_PRO_ASYNC , apiEndpoint : undefined } ,
51+ team : {
52+ sync : env . RATE_LIMIT_TEAM_SYNC ,
53+ async : env . RATE_LIMIT_TEAM_ASYNC ,
54+ apiEndpoint : undefined ,
55+ } ,
56+ enterprise : {
57+ sync : env . RATE_LIMIT_ENTERPRISE_SYNC ,
58+ async : env . RATE_LIMIT_ENTERPRISE_ASYNC ,
59+ apiEndpoint : undefined ,
60+ } ,
61+ }
62+
63+ const rate = Number . parseInt ( envVarMap [ plan ] [ type ] || '' ) || DEFAULT_RATE_LIMITS [ plan ] [ type ]
64+ return createBucketConfig ( rate )
65+ }
66+
2967export const RATE_LIMITS : Record < SubscriptionPlan , RateLimitConfig > = {
3068 free : {
31- sync : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_FREE_SYNC ) || 50 ) ,
32- async : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_FREE_ASYNC ) || 200 ) ,
33- apiEndpoint : createBucketConfig ( 30 ) ,
69+ sync : getRateLimitForPlan ( 'free' , 'sync' ) ,
70+ async : getRateLimitForPlan ( 'free' , 'async' ) ,
71+ apiEndpoint : getRateLimitForPlan ( 'free' , 'apiEndpoint' ) ,
3472 } ,
3573 pro : {
36- sync : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_PRO_SYNC ) || 150 ) ,
37- async : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_PRO_ASYNC ) || 1000 ) ,
38- apiEndpoint : createBucketConfig ( 100 ) ,
74+ sync : getRateLimitForPlan ( 'pro' , 'sync' ) ,
75+ async : getRateLimitForPlan ( 'pro' , 'async' ) ,
76+ apiEndpoint : getRateLimitForPlan ( 'pro' , 'apiEndpoint' ) ,
3977 } ,
4078 team : {
41- sync : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_TEAM_SYNC ) || 300 ) ,
42- async : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_TEAM_ASYNC ) || 2500 ) ,
43- apiEndpoint : createBucketConfig ( 200 ) ,
79+ sync : getRateLimitForPlan ( 'team' , 'sync' ) ,
80+ async : getRateLimitForPlan ( 'team' , 'async' ) ,
81+ apiEndpoint : getRateLimitForPlan ( 'team' , 'apiEndpoint' ) ,
4482 } ,
4583 enterprise : {
46- sync : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_ENTERPRISE_SYNC ) || 600 ) ,
47- async : createBucketConfig ( Number . parseInt ( env . RATE_LIMIT_ENTERPRISE_ASYNC ) || 5000 ) ,
48- apiEndpoint : createBucketConfig ( 500 ) ,
84+ sync : getRateLimitForPlan ( 'enterprise' , 'sync' ) ,
85+ async : getRateLimitForPlan ( 'enterprise' , 'async' ) ,
86+ apiEndpoint : getRateLimitForPlan ( 'enterprise' , 'apiEndpoint' ) ,
4987 } ,
5088}
5189
90+ export function getRateLimit (
91+ plan : SubscriptionPlan | undefined ,
92+ type : RateLimitCounterType
93+ ) : TokenBucketConfig {
94+ const key = toConfigKey ( type )
95+ if ( ! isBillingEnabled ) {
96+ return RATE_LIMITS . free [ key ]
97+ }
98+ return RATE_LIMITS [ plan || 'free' ] [ key ]
99+ }
100+
52101export class RateLimitError extends Error {
53102 statusCode : number
54103 constructor ( message : string , statusCode = 429 ) {
0 commit comments