@upstash/ratelimit 0.0.0-ci.b1700114539281dffd8cdc735b109024d3062db7-20241010102154 → 0.0.0-ci.b7f9ea418a9003054c47927b12f4b106261fb65b-20251023085337

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.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Aggregate } from '@upstash/core-analytics';
2
- import { Pipeline } from '@upstash/redis';
2
+ import { Redis as Redis$2 } from '@upstash/redis';
3
3
 
4
4
  /**
5
5
  * EphemeralCache is used to block certain identifiers right away in case they have already exceeded the ratelimit.
@@ -12,13 +12,13 @@ type EphemeralCache = {
12
12
  blockUntil: (identifier: string, reset: number) => void;
13
13
  set: (key: string, value: number) => void;
14
14
  get: (key: string) => number | null;
15
- incr: (key: string) => number;
15
+ incr: (key: string, incrementAmount?: number) => number;
16
16
  pop: (key: string) => void;
17
17
  empty: () => void;
18
18
  size: () => number;
19
19
  };
20
20
  type RegionContext = {
21
- redis: Redis;
21
+ redis: Redis$1;
22
22
  cache?: EphemeralCache;
23
23
  };
24
24
  type MultiRegionContext = {
@@ -90,7 +90,6 @@ type Algorithm<TContext> = () => {
90
90
  }>;
91
91
  resetTokens: (ctx: TContext, identifier: string) => Promise<void>;
92
92
  };
93
- type IsDenied = 0 | 1;
94
93
  type DeniedValue = string | undefined;
95
94
  type LimitOptions = {
96
95
  geo?: Geo;
@@ -99,20 +98,7 @@ type LimitOptions = {
99
98
  userAgent?: string;
100
99
  country?: string;
101
100
  };
102
- /**
103
- * This is all we need from the redis sdk.
104
- */
105
- type Redis = {
106
- sadd: <TData>(key: string, ...members: TData[]) => Promise<number>;
107
- hset: <TValue>(key: string, obj: {
108
- [key: string]: TValue;
109
- }) => Promise<number>;
110
- eval: <TArgs extends unknown[], TData = unknown>(...args: [script: string, keys: string[], args: TArgs]) => Promise<TData>;
111
- evalsha: <TArgs extends unknown[], TData = unknown>(...args: [sha1: string, keys: string[], args: TArgs]) => Promise<TData>;
112
- scriptLoad: (...args: [script: string]) => Promise<string>;
113
- smismember: (key: string, members: string[]) => Promise<IsDenied[]>;
114
- multi: () => Pipeline;
115
- };
101
+ type Redis$1 = Redis$2;
116
102
 
117
103
  type Geo = {
118
104
  country?: string;
@@ -132,7 +118,7 @@ type Event = Geo & {
132
118
  success: EventSuccess;
133
119
  };
134
120
  type AnalyticsConfig = {
135
- redis: Redis;
121
+ redis: Redis$1;
136
122
  prefix?: string;
137
123
  };
138
124
  /**
@@ -259,7 +245,7 @@ declare abstract class Ratelimit<TContext extends Context> {
259
245
  protected readonly ctx: TContext;
260
246
  protected readonly prefix: string;
261
247
  protected readonly timeout: number;
262
- protected readonly primaryRedis: Redis;
248
+ protected readonly primaryRedis: Redis$1;
263
249
  protected readonly analytics?: Analytics;
264
250
  protected readonly enableProtection: boolean;
265
251
  protected readonly denyListThreshold: number;
@@ -384,7 +370,7 @@ type MultiRegionRatelimitConfig = {
384
370
  * Instances of `@upstash/redis`
385
371
  * @see https://github.com/upstash/upstash-redis#quick-start
386
372
  */
387
- redis: Redis[];
373
+ redis: Redis$1[];
388
374
  /**
389
375
  * The ratelimiter function to use.
390
376
  *
@@ -511,6 +497,7 @@ declare class MultiRegionRatelimit extends Ratelimit<MultiRegionContext> {
511
497
  window: Duration): Algorithm<MultiRegionContext>;
512
498
  }
513
499
 
500
+ type Redis = Pick<Redis$1, "evalsha" | "get" | "set">;
514
501
  type RegionRatelimitConfig = {
515
502
  /**
516
503
  * Instance of `@upstash/redis`
@@ -743,7 +730,7 @@ declare class ThresholdError extends Error {
743
730
  * passed, ttl is infferred from current time.
744
731
  * @returns list of ips which are not in the deny list
745
732
  */
746
- declare const updateIpDenyList: (redis: Redis, prefix: string, threshold: number, ttl?: number) => Promise<unknown[]>;
733
+ declare const updateIpDenyList: (redis: Redis$1, prefix: string, threshold: number, ttl?: number) => Promise<unknown[]>;
747
734
  /**
748
735
  * Disables the ip deny list by removing the ip deny list from the all
749
736
  * set and removing the ip deny list. Also sets the status key to disabled
@@ -753,7 +740,7 @@ declare const updateIpDenyList: (redis: Redis, prefix: string, threshold: number
753
740
  * @param prefix ratelimit prefix
754
741
  * @returns
755
742
  */
756
- declare const disableIpDenyList: (redis: Redis, prefix: string) => Promise<unknown[]>;
743
+ declare const disableIpDenyList: (redis: Redis$1, prefix: string) => Promise<unknown[]>;
757
744
 
758
745
  type ipDenyList_ThresholdError = ThresholdError;
759
746
  declare const ipDenyList_ThresholdError: typeof ThresholdError;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Aggregate } from '@upstash/core-analytics';
2
- import { Pipeline } from '@upstash/redis';
2
+ import { Redis as Redis$2 } from '@upstash/redis';
3
3
 
4
4
  /**
5
5
  * EphemeralCache is used to block certain identifiers right away in case they have already exceeded the ratelimit.
@@ -12,13 +12,13 @@ type EphemeralCache = {
12
12
  blockUntil: (identifier: string, reset: number) => void;
13
13
  set: (key: string, value: number) => void;
14
14
  get: (key: string) => number | null;
15
- incr: (key: string) => number;
15
+ incr: (key: string, incrementAmount?: number) => number;
16
16
  pop: (key: string) => void;
17
17
  empty: () => void;
18
18
  size: () => number;
19
19
  };
20
20
  type RegionContext = {
21
- redis: Redis;
21
+ redis: Redis$1;
22
22
  cache?: EphemeralCache;
23
23
  };
24
24
  type MultiRegionContext = {
@@ -90,7 +90,6 @@ type Algorithm<TContext> = () => {
90
90
  }>;
91
91
  resetTokens: (ctx: TContext, identifier: string) => Promise<void>;
92
92
  };
93
- type IsDenied = 0 | 1;
94
93
  type DeniedValue = string | undefined;
95
94
  type LimitOptions = {
96
95
  geo?: Geo;
@@ -99,20 +98,7 @@ type LimitOptions = {
99
98
  userAgent?: string;
100
99
  country?: string;
101
100
  };
102
- /**
103
- * This is all we need from the redis sdk.
104
- */
105
- type Redis = {
106
- sadd: <TData>(key: string, ...members: TData[]) => Promise<number>;
107
- hset: <TValue>(key: string, obj: {
108
- [key: string]: TValue;
109
- }) => Promise<number>;
110
- eval: <TArgs extends unknown[], TData = unknown>(...args: [script: string, keys: string[], args: TArgs]) => Promise<TData>;
111
- evalsha: <TArgs extends unknown[], TData = unknown>(...args: [sha1: string, keys: string[], args: TArgs]) => Promise<TData>;
112
- scriptLoad: (...args: [script: string]) => Promise<string>;
113
- smismember: (key: string, members: string[]) => Promise<IsDenied[]>;
114
- multi: () => Pipeline;
115
- };
101
+ type Redis$1 = Redis$2;
116
102
 
117
103
  type Geo = {
118
104
  country?: string;
@@ -132,7 +118,7 @@ type Event = Geo & {
132
118
  success: EventSuccess;
133
119
  };
134
120
  type AnalyticsConfig = {
135
- redis: Redis;
121
+ redis: Redis$1;
136
122
  prefix?: string;
137
123
  };
138
124
  /**
@@ -259,7 +245,7 @@ declare abstract class Ratelimit<TContext extends Context> {
259
245
  protected readonly ctx: TContext;
260
246
  protected readonly prefix: string;
261
247
  protected readonly timeout: number;
262
- protected readonly primaryRedis: Redis;
248
+ protected readonly primaryRedis: Redis$1;
263
249
  protected readonly analytics?: Analytics;
264
250
  protected readonly enableProtection: boolean;
265
251
  protected readonly denyListThreshold: number;
@@ -384,7 +370,7 @@ type MultiRegionRatelimitConfig = {
384
370
  * Instances of `@upstash/redis`
385
371
  * @see https://github.com/upstash/upstash-redis#quick-start
386
372
  */
387
- redis: Redis[];
373
+ redis: Redis$1[];
388
374
  /**
389
375
  * The ratelimiter function to use.
390
376
  *
@@ -511,6 +497,7 @@ declare class MultiRegionRatelimit extends Ratelimit<MultiRegionContext> {
511
497
  window: Duration): Algorithm<MultiRegionContext>;
512
498
  }
513
499
 
500
+ type Redis = Pick<Redis$1, "evalsha" | "get" | "set">;
514
501
  type RegionRatelimitConfig = {
515
502
  /**
516
503
  * Instance of `@upstash/redis`
@@ -743,7 +730,7 @@ declare class ThresholdError extends Error {
743
730
  * passed, ttl is infferred from current time.
744
731
  * @returns list of ips which are not in the deny list
745
732
  */
746
- declare const updateIpDenyList: (redis: Redis, prefix: string, threshold: number, ttl?: number) => Promise<unknown[]>;
733
+ declare const updateIpDenyList: (redis: Redis$1, prefix: string, threshold: number, ttl?: number) => Promise<unknown[]>;
747
734
  /**
748
735
  * Disables the ip deny list by removing the ip deny list from the all
749
736
  * set and removing the ip deny list. Also sets the status key to disabled
@@ -753,7 +740,7 @@ declare const updateIpDenyList: (redis: Redis, prefix: string, threshold: number
753
740
  * @param prefix ratelimit prefix
754
741
  * @returns
755
742
  */
756
- declare const disableIpDenyList: (redis: Redis, prefix: string) => Promise<unknown[]>;
743
+ declare const disableIpDenyList: (redis: Redis$1, prefix: string) => Promise<unknown[]>;
757
744
 
758
745
  type ipDenyList_ThresholdError = ThresholdError;
759
746
  declare const ipDenyList_ThresholdError: typeof ThresholdError;
package/dist/index.js CHANGED
@@ -115,9 +115,9 @@ var Cache = class {
115
115
  get(key) {
116
116
  return this.cache.get(key) || null;
117
117
  }
118
- incr(key) {
118
+ incr(key, incrementAmount = 1) {
119
119
  let value = this.cache.get(key) ?? 0;
120
- value += 1;
120
+ value += incrementAmount;
121
121
  this.cache.set(key, value);
122
122
  return value;
123
123
  }
@@ -168,13 +168,7 @@ var safeEval = async (ctx, script, keys, args) => {
168
168
  return await ctx.redis.evalsha(script.hash, keys, args);
169
169
  } catch (error) {
170
170
  if (`${error}`.includes("NOSCRIPT")) {
171
- const hash = await ctx.redis.scriptLoad(script.script);
172
- if (hash !== script.hash) {
173
- console.warn(
174
- "Upstash Ratelimit: Expected hash and the hash received from Redis are different. Ratelimit will work as usual but performance will be reduced."
175
- );
176
- }
177
- return await ctx.redis.evalsha(hash, keys, args);
171
+ return await ctx.redis.eval(script.script, keys, args);
178
172
  }
179
173
  throw error;
180
174
  }
@@ -600,7 +594,7 @@ var updateIpDenyList = async (redis, prefix, threshold, ttl) => {
600
594
  const transaction = redis.multi();
601
595
  transaction.sdiffstore(allDenyLists, allDenyLists, ipDenyList);
602
596
  transaction.del(ipDenyList);
603
- transaction.sadd(ipDenyList, ...allIps);
597
+ transaction.sadd(ipDenyList, allIps.at(0), ...allIps.slice(1));
604
598
  transaction.sdiffstore(ipDenyList, ipDenyList, allDenyLists);
605
599
  transaction.sunionstore(allDenyLists, allDenyLists, ipDenyList);
606
600
  transaction.set(statusKey, "valid", { px: ttl ?? getIpListTTL() });
@@ -925,7 +919,7 @@ var Ratelimit = class {
925
919
  */
926
920
  getDefinedMembers = (identifier, req) => {
927
921
  const members = [identifier, req?.ip, req?.userAgent, req?.country];
928
- return members.filter((item) => Boolean(item));
922
+ return members.filter(Boolean);
929
923
  };
930
924
  };
931
925
 
@@ -1580,7 +1574,7 @@ var RegionRatelimit = class extends Ratelimit {
1580
1574
  const incrementBy = rate ? Math.max(1, rate) : 1;
1581
1575
  const hit = typeof ctx.cache.get(key) === "number";
1582
1576
  if (hit) {
1583
- const cachedTokensAfterUpdate = ctx.cache.incr(key);
1577
+ const cachedTokensAfterUpdate = ctx.cache.incr(key, incrementBy);
1584
1578
  const success = cachedTokensAfterUpdate < tokens;
1585
1579
  const pending = success ? safeEval(
1586
1580
  ctx,