@ooneex/rate-limit 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,8 +1,5 @@
1
- import { Exception } from "@ooneex/exception";
2
- declare class RateLimitException extends Exception {
3
- constructor(message: string, data?: Record<string, unknown>);
4
- }
5
- import { AppEnv } from "@ooneex/app-env";
1
+ import { EContainerScope } from "@ooneex/container";
2
+ import { Duration } from "@upstash/ratelimit";
6
3
  type RateLimiterClassType = new (...args: any[]) => IRateLimiter;
7
4
  type RedisRateLimiterOptionsType = {
8
5
  connectionString?: string;
@@ -14,6 +11,27 @@ type RedisRateLimiterOptionsType = {
14
11
  enableAutoPipelining?: boolean;
15
12
  tls?: boolean | object;
16
13
  };
14
+ type UpstashAlgorithmType = {
15
+ type: "fixedWindow";
16
+ limit: number;
17
+ window: Duration;
18
+ } | {
19
+ type: "slidingWindow";
20
+ limit: number;
21
+ window: Duration;
22
+ } | {
23
+ type: "tokenBucket";
24
+ refillRate: number;
25
+ interval: Duration;
26
+ maxTokens: number;
27
+ };
28
+ type UpstashRedisRateLimiterOptionsType = {
29
+ url?: string;
30
+ token?: string;
31
+ algorithm?: UpstashAlgorithmType;
32
+ prefix?: string;
33
+ analytics?: boolean;
34
+ };
17
35
  type RateLimitResultType = {
18
36
  limited: boolean;
19
37
  remaining: number;
@@ -21,18 +39,40 @@ type RateLimitResultType = {
21
39
  resetAt: Date;
22
40
  };
23
41
  interface IRateLimiter {
24
- check: (key: string, limit: number, windowSeconds: number) => Promise<RateLimitResultType>;
42
+ check: (key: string) => Promise<RateLimitResultType>;
43
+ isLimited: (key: string) => Promise<boolean>;
25
44
  reset: (key: string) => Promise<boolean>;
26
45
  getCount: (key: string) => Promise<number>;
27
46
  }
47
+ declare const decorator: {
48
+ rateLimit: (scope?: EContainerScope) => (target: RateLimiterClassType) => void;
49
+ };
50
+ import { Exception } from "@ooneex/exception";
51
+ declare class RateLimitException extends Exception {
52
+ constructor(message: string, key: string, data?: Record<string, unknown>);
53
+ }
54
+ import { AppEnv } from "@ooneex/app-env";
28
55
  declare class RedisRateLimiter implements IRateLimiter {
29
56
  private readonly env;
30
57
  private client;
31
58
  constructor(env: AppEnv, options?: RedisRateLimiterOptionsType);
32
59
  private connect;
33
60
  private getKey;
34
- check(key: string, limit: number, windowSeconds: number): Promise<RateLimitResultType>;
61
+ check(key: string): Promise<RateLimitResultType>;
62
+ isLimited(key: string): Promise<boolean>;
63
+ reset(key: string): Promise<boolean>;
64
+ getCount(key: string): Promise<number>;
65
+ }
66
+ import { AppEnv as AppEnv2 } from "@ooneex/app-env";
67
+ declare class UpstashRedisRateLimiter implements IRateLimiter {
68
+ private readonly env;
69
+ private ratelimit;
70
+ private static readonly DEFAULT_ALGORITHM;
71
+ constructor(env: AppEnv2, options?: UpstashRedisRateLimiterOptionsType);
72
+ private buildLimiter;
73
+ check(key: string): Promise<RateLimitResultType>;
74
+ isLimited(key: string): Promise<boolean>;
35
75
  reset(key: string): Promise<boolean>;
36
76
  getCount(key: string): Promise<number>;
37
77
  }
38
- export { RedisRateLimiterOptionsType, RedisRateLimiter, RateLimiterClassType, RateLimitResultType, RateLimitException, IRateLimiter };
78
+ export { decorator, UpstashRedisRateLimiterOptionsType, UpstashRedisRateLimiter, UpstashAlgorithmType, RedisRateLimiterOptionsType, RedisRateLimiter, RateLimiterClassType, RateLimitResultType, RateLimitException, IRateLimiter };
package/dist/index.js CHANGED
@@ -15,13 +15,23 @@ var __legacyMetadataTS = (k, v) => {
15
15
  return Reflect.metadata(k, v);
16
16
  };
17
17
 
18
+ // src/decorators.ts
19
+ import { container, EContainerScope } from "@ooneex/container";
20
+ var decorator = {
21
+ rateLimit: (scope = EContainerScope.Singleton) => {
22
+ return (target) => {
23
+ container.add(target, scope);
24
+ };
25
+ }
26
+ };
18
27
  // src/RateLimitException.ts
19
28
  import { Exception } from "@ooneex/exception";
20
29
  import { HttpStatus } from "@ooneex/http-status";
21
30
 
22
31
  class RateLimitException extends Exception {
23
- constructor(message, data = {}) {
32
+ constructor(message, key, data = {}) {
24
33
  super(message, {
34
+ key,
25
35
  status: HttpStatus.Code.TooManyRequests,
26
36
  data
27
37
  });
@@ -30,7 +40,7 @@ class RateLimitException extends Exception {
30
40
  }
31
41
  // src/RedisRateLimiter.ts
32
42
  import { AppEnv } from "@ooneex/app-env";
33
- import { inject, injectable } from "@ooneex/container";
43
+ import { inject } from "@ooneex/container";
34
44
  class RedisRateLimiter {
35
45
  env;
36
46
  client;
@@ -38,7 +48,7 @@ class RedisRateLimiter {
38
48
  this.env = env;
39
49
  const connectionString = options.connectionString || this.env.RATE_LIMIT_REDIS_URL;
40
50
  if (!connectionString) {
41
- throw new RateLimitException("Redis connection string is required. Please provide a connection string either through the constructor options or set the RATE_LIMIT_REDIS_URL environment variable.");
51
+ throw new RateLimitException("Redis connection string is required. Please provide a connection string either through the constructor options or set the RATE_LIMIT_REDIS_URL environment variable.", "RATE_LIMIT_CONNECTION_FAILED");
42
52
  }
43
53
  const { connectionString: _, ...userOptions } = options;
44
54
  const defaultOptions = {
@@ -60,7 +70,9 @@ class RedisRateLimiter {
60
70
  getKey(key) {
61
71
  return `ratelimit:${key}`;
62
72
  }
63
- async check(key, limit, windowSeconds) {
73
+ async check(key) {
74
+ const limit = 120;
75
+ const windowSeconds = 60;
64
76
  try {
65
77
  await this.connect();
66
78
  const rateLimitKey = this.getKey(key);
@@ -77,9 +89,13 @@ class RedisRateLimiter {
77
89
  resetAt
78
90
  };
79
91
  } catch (error) {
80
- throw new RateLimitException(`Failed to check rate limit for key "${key}": ${error}`);
92
+ throw new RateLimitException(`Failed to check rate limit for key "${key}": ${error}`, "RATE_LIMIT_CHECK_FAILED");
81
93
  }
82
94
  }
95
+ async isLimited(key) {
96
+ const result = await this.check(key);
97
+ return result.limited;
98
+ }
83
99
  async reset(key) {
84
100
  try {
85
101
  await this.connect();
@@ -87,7 +103,7 @@ class RedisRateLimiter {
87
103
  const result = await this.client.del(rateLimitKey);
88
104
  return result > 0;
89
105
  } catch (error) {
90
- throw new RateLimitException(`Failed to reset rate limit for key "${key}": ${error}`);
106
+ throw new RateLimitException(`Failed to reset rate limit for key "${key}": ${error}`, "RATE_LIMIT_RESET_FAILED");
91
107
  }
92
108
  }
93
109
  async getCount(key) {
@@ -100,21 +116,104 @@ class RedisRateLimiter {
100
116
  }
101
117
  return Number.parseInt(value, 10);
102
118
  } catch (error) {
103
- throw new RateLimitException(`Failed to get count for key "${key}": ${error}`);
119
+ throw new RateLimitException(`Failed to get count for key "${key}": ${error}`, "RATE_LIMIT_COUNT_FAILED");
104
120
  }
105
121
  }
106
122
  }
107
123
  RedisRateLimiter = __legacyDecorateClassTS([
108
- injectable(),
124
+ decorator.rateLimit(),
109
125
  __legacyDecorateParamTS(0, inject(AppEnv)),
110
126
  __legacyMetadataTS("design:paramtypes", [
111
127
  typeof AppEnv === "undefined" ? Object : AppEnv,
112
128
  typeof RedisRateLimiterOptionsType === "undefined" ? Object : RedisRateLimiterOptionsType
113
129
  ])
114
130
  ], RedisRateLimiter);
131
+ // src/UpstashRedisRateLimiter.ts
132
+ import { AppEnv as AppEnv2 } from "@ooneex/app-env";
133
+ import { inject as inject2 } from "@ooneex/container";
134
+ import { Ratelimit } from "@upstash/ratelimit";
135
+ import { Redis } from "@upstash/redis";
136
+ class UpstashRedisRateLimiter {
137
+ env;
138
+ ratelimit;
139
+ static DEFAULT_ALGORITHM = {
140
+ type: "slidingWindow",
141
+ limit: 120,
142
+ window: "60 s"
143
+ };
144
+ constructor(env, options = {}) {
145
+ this.env = env;
146
+ const url = options.url || this.env.RATE_LIMIT_UPSTASH_REDIS_URL;
147
+ const token = options.token || this.env.RATE_LIMIT_UPSTASH_REDIS_TOKEN;
148
+ if (!url || !token) {
149
+ throw new RateLimitException("Upstash Redis URL and token are required. Please provide them through the constructor options or set the RATE_LIMIT_UPSTASH_REDIS_URL and RATE_LIMIT_UPSTASH_REDIS_TOKEN environment variables.", "RATE_LIMIT_CONNECTION_FAILED");
150
+ }
151
+ const redis = new Redis({ url, token });
152
+ const limiter = this.buildLimiter(options.algorithm);
153
+ this.ratelimit = new Ratelimit({
154
+ redis,
155
+ limiter,
156
+ prefix: options.prefix ?? "@ooneex/ratelimit",
157
+ analytics: options.analytics ?? true
158
+ });
159
+ }
160
+ buildLimiter(algorithm = UpstashRedisRateLimiter.DEFAULT_ALGORITHM) {
161
+ switch (algorithm.type) {
162
+ case "fixedWindow":
163
+ return Ratelimit.fixedWindow(algorithm.limit, algorithm.window);
164
+ case "slidingWindow":
165
+ return Ratelimit.slidingWindow(algorithm.limit, algorithm.window);
166
+ case "tokenBucket":
167
+ return Ratelimit.tokenBucket(algorithm.refillRate, algorithm.interval, algorithm.maxTokens);
168
+ }
169
+ }
170
+ async check(key) {
171
+ try {
172
+ const result = await this.ratelimit.limit(key);
173
+ return {
174
+ limited: !result.success,
175
+ remaining: result.remaining,
176
+ total: result.limit,
177
+ resetAt: new Date(result.reset)
178
+ };
179
+ } catch (error) {
180
+ throw new RateLimitException(`Failed to check rate limit for key "${key}": ${error}`, "RATE_LIMIT_CHECK_FAILED");
181
+ }
182
+ }
183
+ async isLimited(key) {
184
+ const result = await this.check(key);
185
+ return result.limited;
186
+ }
187
+ async reset(key) {
188
+ try {
189
+ await this.ratelimit.resetUsedTokens(key);
190
+ return true;
191
+ } catch (error) {
192
+ throw new RateLimitException(`Failed to reset rate limit for key "${key}": ${error}`, "RATE_LIMIT_RESET_FAILED");
193
+ }
194
+ }
195
+ async getCount(key) {
196
+ try {
197
+ const { remaining } = await this.ratelimit.getRemaining(key);
198
+ return remaining;
199
+ } catch (error) {
200
+ throw new RateLimitException(`Failed to get count for key "${key}": ${error}`, "RATE_LIMIT_COUNT_FAILED");
201
+ }
202
+ }
203
+ }
204
+ UpstashRedisRateLimiter = __legacyDecorateClassTS([
205
+ decorator.rateLimit(),
206
+ __legacyDecorateParamTS(0, inject2(AppEnv2)),
207
+ __legacyMetadataTS("design:paramtypes", [
208
+ typeof AppEnv2 === "undefined" ? Object : AppEnv2,
209
+ typeof UpstashRedisRateLimiterOptionsType === "undefined" ? Object : UpstashRedisRateLimiterOptionsType
210
+ ])
211
+ ], UpstashRedisRateLimiter);
115
212
  export {
213
+ decorator,
214
+ UpstashRedisRateLimiter,
116
215
  RedisRateLimiter,
117
216
  RateLimitException
118
217
  };
119
218
 
120
- //# debugId=66919C914CDF5FD864756E2164756E21
219
+ //# debugId=8F06C17BF8E11C5C64756E2164756E21
package/dist/index.js.map CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["src/RateLimitException.ts", "src/RedisRateLimiter.ts"],
3
+ "sources": ["src/decorators.ts", "src/RateLimitException.ts", "src/RedisRateLimiter.ts", "src/UpstashRedisRateLimiter.ts"],
4
4
  "sourcesContent": [
5
- "import { Exception } from \"@ooneex/exception\";\nimport { HttpStatus } from \"@ooneex/http-status\";\n\nexport class RateLimitException extends Exception {\n constructor(message: string, data: Record<string, unknown> = {}) {\n super(message, {\n status: HttpStatus.Code.TooManyRequests,\n data,\n });\n this.name = \"RateLimitException\";\n }\n}\n",
6
- "import { AppEnv } from \"@ooneex/app-env\";\nimport { inject, injectable } from \"@ooneex/container\";\nimport { RateLimitException } from \"./RateLimitException\";\nimport type { IRateLimiter, RateLimitResultType, RedisRateLimiterOptionsType } from \"./types\";\n\n@injectable()\nexport class RedisRateLimiter implements IRateLimiter {\n private client: Bun.RedisClient;\n\n constructor(\n @inject(AppEnv) private readonly env: AppEnv,\n options: RedisRateLimiterOptionsType = {},\n ) {\n const connectionString = options.connectionString || this.env.RATE_LIMIT_REDIS_URL;\n\n if (!connectionString) {\n throw new RateLimitException(\n \"Redis connection string is required. Please provide a connection string either through the constructor options or set the RATE_LIMIT_REDIS_URL environment variable.\",\n );\n }\n\n const { connectionString: _, ...userOptions } = options;\n\n const defaultOptions = {\n connectionTimeout: 10_000,\n idleTimeout: 30_000,\n autoReconnect: true,\n maxRetries: 3,\n enableOfflineQueue: true,\n enableAutoPipelining: true,\n };\n\n const clientOptions = { ...defaultOptions, ...userOptions };\n\n this.client = new Bun.RedisClient(connectionString, clientOptions);\n }\n\n private async connect(): Promise<void> {\n if (!this.client.connected) {\n await this.client.connect();\n }\n }\n\n private getKey(key: string): string {\n return `ratelimit:${key}`;\n }\n\n public async check(key: string, limit: number, windowSeconds: number): Promise<RateLimitResultType> {\n try {\n await this.connect();\n\n const rateLimitKey = this.getKey(key);\n\n // Increment counter\n const count = await this.client.incr(rateLimitKey);\n\n // Set expiry if this is the first request in window\n if (count === 1) {\n await this.client.expire(rateLimitKey, windowSeconds);\n }\n\n // Get TTL for reset time calculation\n const ttl = await this.client.ttl(rateLimitKey);\n const resetAt = new Date(Date.now() + ttl * 1000);\n\n return {\n limited: count > limit,\n remaining: Math.max(0, limit - count),\n total: limit,\n resetAt,\n };\n } catch (error) {\n throw new RateLimitException(`Failed to check rate limit for key \"${key}\": ${error}`);\n }\n }\n\n public async reset(key: string): Promise<boolean> {\n try {\n await this.connect();\n\n const rateLimitKey = this.getKey(key);\n const result = await this.client.del(rateLimitKey);\n\n return result > 0;\n } catch (error) {\n throw new RateLimitException(`Failed to reset rate limit for key \"${key}\": ${error}`);\n }\n }\n\n public async getCount(key: string): Promise<number> {\n try {\n await this.connect();\n\n const rateLimitKey = this.getKey(key);\n const value = await this.client.get(rateLimitKey);\n\n if (value === null) {\n return 0;\n }\n\n return Number.parseInt(value, 10);\n } catch (error) {\n throw new RateLimitException(`Failed to get count for key \"${key}\": ${error}`);\n }\n }\n}\n"
5
+ "import { container, EContainerScope } from \"@ooneex/container\";\nimport type { RateLimiterClassType } from \"./types\";\n\nexport const decorator = {\n rateLimit: (scope: EContainerScope = EContainerScope.Singleton) => {\n return (target: RateLimiterClassType): void => {\n container.add(target, scope);\n };\n },\n};\n",
6
+ "import { Exception } from \"@ooneex/exception\";\nimport { HttpStatus } from \"@ooneex/http-status\";\n\nexport class RateLimitException extends Exception {\n constructor(message: string, key: string, data: Record<string, unknown> = {}) {\n super(message, {\n key,\n status: HttpStatus.Code.TooManyRequests,\n data,\n });\n this.name = \"RateLimitException\";\n }\n}\n",
7
+ "import { AppEnv } from \"@ooneex/app-env\";\nimport { inject } from \"@ooneex/container\";\nimport { decorator } from \"./decorators\";\nimport { RateLimitException } from \"./RateLimitException\";\nimport type { IRateLimiter, RateLimitResultType, RedisRateLimiterOptionsType } from \"./types\";\n\n@decorator.rateLimit()\nexport class RedisRateLimiter implements IRateLimiter {\n private client: Bun.RedisClient;\n\n constructor(\n @inject(AppEnv) private readonly env: AppEnv,\n options: RedisRateLimiterOptionsType = {},\n ) {\n const connectionString = options.connectionString || this.env.RATE_LIMIT_REDIS_URL;\n\n if (!connectionString) {\n throw new RateLimitException(\n \"Redis connection string is required. Please provide a connection string either through the constructor options or set the RATE_LIMIT_REDIS_URL environment variable.\",\n \"RATE_LIMIT_CONNECTION_FAILED\",\n );\n }\n\n const { connectionString: _, ...userOptions } = options;\n\n const defaultOptions = {\n connectionTimeout: 10_000,\n idleTimeout: 30_000,\n autoReconnect: true,\n maxRetries: 3,\n enableOfflineQueue: true,\n enableAutoPipelining: true,\n };\n\n const clientOptions = { ...defaultOptions, ...userOptions };\n\n this.client = new Bun.RedisClient(connectionString, clientOptions);\n }\n\n private async connect(): Promise<void> {\n if (!this.client.connected) {\n await this.client.connect();\n }\n }\n\n private getKey(key: string): string {\n return `ratelimit:${key}`;\n }\n\n public async check(key: string): Promise<RateLimitResultType> {\n const limit = 120;\n const windowSeconds = 60;\n try {\n await this.connect();\n\n const rateLimitKey = this.getKey(key);\n\n // Increment counter\n const count = await this.client.incr(rateLimitKey);\n\n // Set expiry if this is the first request in window\n if (count === 1) {\n await this.client.expire(rateLimitKey, windowSeconds);\n }\n\n // Get TTL for reset time calculation\n const ttl = await this.client.ttl(rateLimitKey);\n const resetAt = new Date(Date.now() + ttl * 1000);\n\n return {\n limited: count > limit,\n remaining: Math.max(0, limit - count),\n total: limit,\n resetAt,\n };\n } catch (error: unknown) {\n throw new RateLimitException(`Failed to check rate limit for key \"${key}\": ${error}`, \"RATE_LIMIT_CHECK_FAILED\");\n }\n }\n\n public async isLimited(key: string): Promise<boolean> {\n const result = await this.check(key);\n\n return result.limited;\n }\n\n public async reset(key: string): Promise<boolean> {\n try {\n await this.connect();\n\n const rateLimitKey = this.getKey(key);\n const result = await this.client.del(rateLimitKey);\n\n return result > 0;\n } catch (error: unknown) {\n throw new RateLimitException(`Failed to reset rate limit for key \"${key}\": ${error}`, \"RATE_LIMIT_RESET_FAILED\");\n }\n }\n\n public async getCount(key: string): Promise<number> {\n try {\n await this.connect();\n\n const rateLimitKey = this.getKey(key);\n const value = await this.client.get(rateLimitKey);\n\n if (value === null) {\n return 0;\n }\n\n return Number.parseInt(value, 10);\n } catch (error: unknown) {\n throw new RateLimitException(`Failed to get count for key \"${key}\": ${error}`, \"RATE_LIMIT_COUNT_FAILED\");\n }\n }\n}\n",
8
+ "import { AppEnv } from \"@ooneex/app-env\";\nimport { inject } from \"@ooneex/container\";\nimport { Ratelimit } from \"@upstash/ratelimit\";\nimport { Redis } from \"@upstash/redis\";\nimport { decorator } from \"./decorators\";\nimport { RateLimitException } from \"./RateLimitException\";\nimport type {\n IRateLimiter,\n RateLimitResultType,\n UpstashAlgorithmType,\n UpstashRedisRateLimiterOptionsType,\n} from \"./types\";\n\n@decorator.rateLimit()\nexport class UpstashRedisRateLimiter implements IRateLimiter {\n private ratelimit: Ratelimit;\n // Default: 120 requests per 60-second sliding window (high traffic)\n private static readonly DEFAULT_ALGORITHM: UpstashAlgorithmType = {\n type: \"slidingWindow\",\n limit: 120,\n window: \"60 s\",\n };\n\n constructor(\n @inject(AppEnv) private readonly env: AppEnv,\n options: UpstashRedisRateLimiterOptionsType = {},\n ) {\n const url = options.url || this.env.RATE_LIMIT_UPSTASH_REDIS_URL;\n const token = options.token || this.env.RATE_LIMIT_UPSTASH_REDIS_TOKEN;\n\n if (!url || !token) {\n throw new RateLimitException(\n \"Upstash Redis URL and token are required. Please provide them through the constructor options or set the RATE_LIMIT_UPSTASH_REDIS_URL and RATE_LIMIT_UPSTASH_REDIS_TOKEN environment variables.\",\n \"RATE_LIMIT_CONNECTION_FAILED\",\n );\n }\n\n const redis = new Redis({ url, token });\n const limiter = this.buildLimiter(options.algorithm);\n\n this.ratelimit = new Ratelimit({\n redis,\n limiter,\n prefix: options.prefix ?? \"@ooneex/ratelimit\",\n analytics: options.analytics ?? true,\n });\n }\n\n private buildLimiter(algorithm: UpstashAlgorithmType = UpstashRedisRateLimiter.DEFAULT_ALGORITHM) {\n switch (algorithm.type) {\n case \"fixedWindow\":\n return Ratelimit.fixedWindow(algorithm.limit, algorithm.window);\n case \"slidingWindow\":\n return Ratelimit.slidingWindow(algorithm.limit, algorithm.window);\n case \"tokenBucket\":\n return Ratelimit.tokenBucket(algorithm.refillRate, algorithm.interval, algorithm.maxTokens);\n }\n }\n\n public async check(key: string): Promise<RateLimitResultType> {\n try {\n const result = await this.ratelimit.limit(key);\n\n return {\n limited: !result.success,\n remaining: result.remaining,\n total: result.limit,\n resetAt: new Date(result.reset),\n };\n } catch (error) {\n throw new RateLimitException(`Failed to check rate limit for key \"${key}\": ${error}`, \"RATE_LIMIT_CHECK_FAILED\");\n }\n }\n\n public async isLimited(key: string): Promise<boolean> {\n const result = await this.check(key);\n\n return result.limited;\n }\n\n public async reset(key: string): Promise<boolean> {\n try {\n await this.ratelimit.resetUsedTokens(key);\n\n return true;\n } catch (error) {\n throw new RateLimitException(`Failed to reset rate limit for key \"${key}\": ${error}`, \"RATE_LIMIT_RESET_FAILED\");\n }\n }\n\n public async getCount(key: string): Promise<number> {\n try {\n const { remaining } = await this.ratelimit.getRemaining(key);\n\n return remaining;\n } catch (error) {\n throw new RateLimitException(`Failed to get count for key \"${key}\": ${error}`, \"RATE_LIMIT_COUNT_FAILED\");\n }\n }\n}\n"
7
9
  ],
8
- "mappings": "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",
9
- "debugId": "66919C914CDF5FD864756E2164756E21",
10
+ "mappings": "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",
11
+ "debugId": "8F06C17BF8E11C5C64756E2164756E21",
10
12
  "names": []
11
13
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ooneex/rate-limit",
3
3
  "description": "API rate limiting middleware with configurable throttling strategies, sliding window counters, and per-client request quota enforcement",
4
- "version": "1.1.3",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -28,14 +28,15 @@
28
28
  "npm:publish": "bun publish --tolerate-republish --force --production --access public"
29
29
  },
30
30
  "peerDependencies": {
31
- "@ooneex/exception": "1.1.2",
32
- "@ooneex/http-status": "1.1.2"
31
+ "@ooneex/exception": "1.1.3",
32
+ "@ooneex/http-status": "1.1.3"
33
33
  },
34
34
  "dependencies": {
35
- "@ooneex/app-env": "1.2.0",
36
- "@ooneex/exception": "1.1.2",
37
- "@ooneex/container": "1.1.2",
38
- "@ooneex/http-status": "1.1.2"
35
+ "@ooneex/app-env": "1.2.1",
36
+ "@ooneex/container": "1.2.1",
37
+ "@ooneex/exception": "1.1.3",
38
+ "@ooneex/http-status": "1.1.3",
39
+ "@upstash/ratelimit": "^2.0.8"
39
40
  },
40
41
  "keywords": [
41
42
  "api",