@upstash/ratelimit 2.0.2 → 2.0.3

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.js CHANGED
@@ -157,38 +157,181 @@ function ms(d) {
157
157
  }
158
158
 
159
159
  // src/hash.ts
160
- var setHash = async (ctx, script, kind) => {
161
- const regionContexts = "redis" in ctx ? [ctx] : ctx.regionContexts;
162
- const hashSample = regionContexts[0].scriptHashes[kind];
163
- if (!hashSample) {
164
- await Promise.all(regionContexts.map(async (context) => {
165
- context.scriptHashes[kind] = await context.redis.scriptLoad(script);
166
- }));
167
- }
168
- ;
169
- };
170
- var safeEval = async (ctx, script, kind, keys, args) => {
171
- if (!ctx.cacheScripts) {
172
- return await ctx.redis.eval(script, keys, args);
173
- }
174
- ;
175
- await setHash(ctx, script, kind);
160
+ var safeEval = async (ctx, script, keys, args) => {
176
161
  try {
177
- return await ctx.redis.evalsha(ctx.scriptHashes[kind], keys, args);
162
+ return await ctx.redis.evalsha(script.hash, keys, args);
178
163
  } catch (error) {
179
164
  if (`${error}`.includes("NOSCRIPT")) {
180
- console.log("Script with the expected hash was not found in redis db. It is probably flushed. Will load another scipt before continuing.");
181
- ctx.scriptHashes[kind] = void 0;
182
- await setHash(ctx, script, kind);
183
- console.log(" New script successfully loaded.");
184
- return await ctx.redis.evalsha(ctx.scriptHashes[kind], keys, args);
165
+ const hash = await ctx.redis.scriptLoad(script.script);
166
+ if (hash !== script.hash) {
167
+ console.warn(
168
+ "Upstash Ratelimit: Expected hash and the hash received from Redis are different. Ratelimit will work as usual but performance will be reduced."
169
+ );
170
+ }
171
+ return await ctx.redis.evalsha(hash, keys, args);
185
172
  }
186
173
  throw error;
187
174
  }
188
175
  };
189
176
 
190
- // src/lua-scripts/multi.ts
177
+ // src/lua-scripts/single.ts
191
178
  var fixedWindowLimitScript = `
179
+ local key = KEYS[1]
180
+ local window = ARGV[1]
181
+ local incrementBy = ARGV[2] -- increment rate per request at a given value, default is 1
182
+
183
+ local r = redis.call("INCRBY", key, incrementBy)
184
+ if r == tonumber(incrementBy) then
185
+ -- The first time this key is set, the value will be equal to incrementBy.
186
+ -- So we only need the expire command once
187
+ redis.call("PEXPIRE", key, window)
188
+ end
189
+
190
+ return r
191
+ `;
192
+ var fixedWindowRemainingTokensScript = `
193
+ local key = KEYS[1]
194
+ local tokens = 0
195
+
196
+ local value = redis.call('GET', key)
197
+ if value then
198
+ tokens = value
199
+ end
200
+ return tokens
201
+ `;
202
+ var slidingWindowLimitScript = `
203
+ local currentKey = KEYS[1] -- identifier including prefixes
204
+ local previousKey = KEYS[2] -- key of the previous bucket
205
+ local tokens = tonumber(ARGV[1]) -- tokens per window
206
+ local now = ARGV[2] -- current timestamp in milliseconds
207
+ local window = ARGV[3] -- interval in milliseconds
208
+ local incrementBy = ARGV[4] -- increment rate per request at a given value, default is 1
209
+
210
+ local requestsInCurrentWindow = redis.call("GET", currentKey)
211
+ if requestsInCurrentWindow == false then
212
+ requestsInCurrentWindow = 0
213
+ end
214
+
215
+ local requestsInPreviousWindow = redis.call("GET", previousKey)
216
+ if requestsInPreviousWindow == false then
217
+ requestsInPreviousWindow = 0
218
+ end
219
+ local percentageInCurrent = ( now % window ) / window
220
+ -- weighted requests to consider from the previous window
221
+ requestsInPreviousWindow = math.floor(( 1 - percentageInCurrent ) * requestsInPreviousWindow)
222
+ if requestsInPreviousWindow + requestsInCurrentWindow >= tokens then
223
+ return -1
224
+ end
225
+
226
+ local newValue = redis.call("INCRBY", currentKey, incrementBy)
227
+ if newValue == tonumber(incrementBy) then
228
+ -- The first time this key is set, the value will be equal to incrementBy.
229
+ -- So we only need the expire command once
230
+ redis.call("PEXPIRE", currentKey, window * 2 + 1000) -- Enough time to overlap with a new window + 1 second
231
+ end
232
+ return tokens - ( newValue + requestsInPreviousWindow )
233
+ `;
234
+ var slidingWindowRemainingTokensScript = `
235
+ local currentKey = KEYS[1] -- identifier including prefixes
236
+ local previousKey = KEYS[2] -- key of the previous bucket
237
+ local now = ARGV[1] -- current timestamp in milliseconds
238
+ local window = ARGV[2] -- interval in milliseconds
239
+
240
+ local requestsInCurrentWindow = redis.call("GET", currentKey)
241
+ if requestsInCurrentWindow == false then
242
+ requestsInCurrentWindow = 0
243
+ end
244
+
245
+ local requestsInPreviousWindow = redis.call("GET", previousKey)
246
+ if requestsInPreviousWindow == false then
247
+ requestsInPreviousWindow = 0
248
+ end
249
+
250
+ local percentageInCurrent = ( now % window ) / window
251
+ -- weighted requests to consider from the previous window
252
+ requestsInPreviousWindow = math.floor(( 1 - percentageInCurrent ) * requestsInPreviousWindow)
253
+
254
+ return requestsInPreviousWindow + requestsInCurrentWindow
255
+ `;
256
+ var tokenBucketLimitScript = `
257
+ local key = KEYS[1] -- identifier including prefixes
258
+ local maxTokens = tonumber(ARGV[1]) -- maximum number of tokens
259
+ local interval = tonumber(ARGV[2]) -- size of the window in milliseconds
260
+ local refillRate = tonumber(ARGV[3]) -- how many tokens are refilled after each interval
261
+ local now = tonumber(ARGV[4]) -- current timestamp in milliseconds
262
+ local incrementBy = tonumber(ARGV[5]) -- how many tokens to consume, default is 1
263
+
264
+ local bucket = redis.call("HMGET", key, "refilledAt", "tokens")
265
+
266
+ local refilledAt
267
+ local tokens
268
+
269
+ if bucket[1] == false then
270
+ refilledAt = now
271
+ tokens = maxTokens
272
+ else
273
+ refilledAt = tonumber(bucket[1])
274
+ tokens = tonumber(bucket[2])
275
+ end
276
+
277
+ if now >= refilledAt + interval then
278
+ local numRefills = math.floor((now - refilledAt) / interval)
279
+ tokens = math.min(maxTokens, tokens + numRefills * refillRate)
280
+
281
+ refilledAt = refilledAt + numRefills * interval
282
+ end
283
+
284
+ if tokens == 0 then
285
+ return {-1, refilledAt + interval}
286
+ end
287
+
288
+ local remaining = tokens - incrementBy
289
+ local expireAt = math.ceil(((maxTokens - remaining) / refillRate)) * interval
290
+
291
+ redis.call("HSET", key, "refilledAt", refilledAt, "tokens", remaining)
292
+ redis.call("PEXPIRE", key, expireAt)
293
+ return {remaining, refilledAt + interval}
294
+ `;
295
+ var tokenBucketIdentifierNotFound = -1;
296
+ var tokenBucketRemainingTokensScript = `
297
+ local key = KEYS[1]
298
+ local maxTokens = tonumber(ARGV[1])
299
+
300
+ local bucket = redis.call("HMGET", key, "refilledAt", "tokens")
301
+
302
+ if bucket[1] == false then
303
+ return {maxTokens, ${tokenBucketIdentifierNotFound}}
304
+ end
305
+
306
+ return {tonumber(bucket[2]), tonumber(bucket[1])}
307
+ `;
308
+ var cachedFixedWindowLimitScript = `
309
+ local key = KEYS[1]
310
+ local window = ARGV[1]
311
+ local incrementBy = ARGV[2] -- increment rate per request at a given value, default is 1
312
+
313
+ local r = redis.call("INCRBY", key, incrementBy)
314
+ if r == incrementBy then
315
+ -- The first time this key is set, the value will be equal to incrementBy.
316
+ -- So we only need the expire command once
317
+ redis.call("PEXPIRE", key, window)
318
+ end
319
+
320
+ return r
321
+ `;
322
+ var cachedFixedWindowRemainingTokenScript = `
323
+ local key = KEYS[1]
324
+ local tokens = 0
325
+
326
+ local value = redis.call('GET', key)
327
+ if value then
328
+ tokens = value
329
+ end
330
+ return tokens
331
+ `;
332
+
333
+ // src/lua-scripts/multi.ts
334
+ var fixedWindowLimitScript2 = `
192
335
  local key = KEYS[1]
193
336
  local id = ARGV[1]
194
337
  local window = ARGV[2]
@@ -204,7 +347,7 @@ var fixedWindowLimitScript = `
204
347
 
205
348
  return fields
206
349
  `;
207
- var fixedWindowRemainingTokensScript = `
350
+ var fixedWindowRemainingTokensScript2 = `
208
351
  local key = KEYS[1]
209
352
  local tokens = 0
210
353
 
@@ -212,7 +355,7 @@ var fixedWindowRemainingTokensScript = `
212
355
 
213
356
  return fields
214
357
  `;
215
- var slidingWindowLimitScript = `
358
+ var slidingWindowLimitScript2 = `
216
359
  local currentKey = KEYS[1] -- identifier including prefixes
217
360
  local previousKey = KEYS[2] -- key of the previous bucket
218
361
  local tokens = tonumber(ARGV[1]) -- tokens per window
@@ -247,7 +390,7 @@ var slidingWindowLimitScript = `
247
390
  end
248
391
  return {currentFields, previousFields, true}
249
392
  `;
250
- var slidingWindowRemainingTokensScript = `
393
+ var slidingWindowRemainingTokensScript2 = `
251
394
  local currentKey = KEYS[1] -- identifier including prefixes
252
395
  local previousKey = KEYS[2] -- key of the previous bucket
253
396
  local now = ARGV[1] -- current timestamp in milliseconds
@@ -296,6 +439,78 @@ var resetScript = `
296
439
  until cursor == "0"
297
440
  `;
298
441
 
442
+ // src/lua-scripts/hash.ts
443
+ var SCRIPTS = {
444
+ singleRegion: {
445
+ fixedWindow: {
446
+ limit: {
447
+ script: fixedWindowLimitScript,
448
+ hash: "b13943e359636db027ad280f1def143f02158c13"
449
+ },
450
+ getRemaining: {
451
+ script: fixedWindowRemainingTokensScript,
452
+ hash: "8c4c341934502aee132643ffbe58ead3450e5208"
453
+ }
454
+ },
455
+ slidingWindow: {
456
+ limit: {
457
+ script: slidingWindowLimitScript,
458
+ hash: "e1391e429b699c780eb0480350cd5b7280fd9213"
459
+ },
460
+ getRemaining: {
461
+ script: slidingWindowRemainingTokensScript,
462
+ hash: "65a73ac5a05bf9712903bc304b77268980c1c417"
463
+ }
464
+ },
465
+ tokenBucket: {
466
+ limit: {
467
+ script: tokenBucketLimitScript,
468
+ hash: "5bece90aeef8189a8cfd28995b479529e270b3c6"
469
+ },
470
+ getRemaining: {
471
+ script: tokenBucketRemainingTokensScript,
472
+ hash: "a15be2bb1db2a15f7c82db06146f9d08983900d0"
473
+ }
474
+ },
475
+ cachedFixedWindow: {
476
+ limit: {
477
+ script: cachedFixedWindowLimitScript,
478
+ hash: "c26b12703dd137939b9a69a3a9b18e906a2d940f"
479
+ },
480
+ getRemaining: {
481
+ script: cachedFixedWindowRemainingTokenScript,
482
+ hash: "8e8f222ccae68b595ee6e3f3bf2199629a62b91a"
483
+ }
484
+ }
485
+ },
486
+ multiRegion: {
487
+ fixedWindow: {
488
+ limit: {
489
+ script: fixedWindowLimitScript2,
490
+ hash: "a8c14f3835aa87bd70e5e2116081b81664abcf5c"
491
+ },
492
+ getRemaining: {
493
+ script: fixedWindowRemainingTokensScript2,
494
+ hash: "8ab8322d0ed5fe5ac8eb08f0c2e4557f1b4816fd"
495
+ }
496
+ },
497
+ slidingWindow: {
498
+ limit: {
499
+ script: slidingWindowLimitScript2,
500
+ hash: "cb4fdc2575056df7c6d422764df0de3a08d6753b"
501
+ },
502
+ getRemaining: {
503
+ script: slidingWindowRemainingTokensScript2,
504
+ hash: "558c9306b7ec54abb50747fe0b17e5d44bd24868"
505
+ }
506
+ }
507
+ }
508
+ };
509
+ var RESET_SCRIPT = {
510
+ script: resetScript,
511
+ hash: "54bd274ddc59fb3be0f42deee2f64322a10e2b50"
512
+ };
513
+
299
514
  // src/types.ts
300
515
  var DenyListExtension = "denyList";
301
516
  var IpDenyListKey = "ipDenyList";
@@ -735,9 +950,7 @@ var MultiRegionRatelimit = class extends Ratelimit {
735
950
  analytics: config.analytics,
736
951
  ctx: {
737
952
  regionContexts: config.redis.map((redis) => ({
738
- redis,
739
- scriptHashes: {},
740
- cacheScripts: config.cacheScripts ?? true
953
+ redis
741
954
  })),
742
955
  cache: config.ephemeralCache ? new Cache(config.ephemeralCache) : void 0
743
956
  }
@@ -786,8 +999,7 @@ var MultiRegionRatelimit = class extends Ratelimit {
786
999
  redis: regionContext.redis,
787
1000
  request: safeEval(
788
1001
  regionContext,
789
- fixedWindowLimitScript,
790
- "limitHash",
1002
+ SCRIPTS.multiRegion.fixedWindow.limit,
791
1003
  [key],
792
1004
  [requestId, windowDuration, incrementBy]
793
1005
  )
@@ -862,8 +1074,7 @@ var MultiRegionRatelimit = class extends Ratelimit {
862
1074
  redis: regionContext.redis,
863
1075
  request: safeEval(
864
1076
  regionContext,
865
- fixedWindowRemainingTokensScript,
866
- "getRemainingHash",
1077
+ SCRIPTS.multiRegion.fixedWindow.getRemaining,
867
1078
  [key],
868
1079
  [null]
869
1080
  )
@@ -889,8 +1100,7 @@ var MultiRegionRatelimit = class extends Ratelimit {
889
1100
  await Promise.all(ctx.regionContexts.map((regionContext) => {
890
1101
  safeEval(
891
1102
  regionContext,
892
- resetScript,
893
- "resetHash",
1103
+ RESET_SCRIPT,
894
1104
  [pattern],
895
1105
  [null]
896
1106
  );
@@ -943,8 +1153,7 @@ var MultiRegionRatelimit = class extends Ratelimit {
943
1153
  redis: regionContext.redis,
944
1154
  request: safeEval(
945
1155
  regionContext,
946
- slidingWindowLimitScript,
947
- "limitHash",
1156
+ SCRIPTS.multiRegion.slidingWindow.limit,
948
1157
  [currentKey, previousKey],
949
1158
  [tokens, now, windowDuration, requestId, incrementBy]
950
1159
  // lua seems to return `1` for true and `null` for false
@@ -1033,8 +1242,7 @@ var MultiRegionRatelimit = class extends Ratelimit {
1033
1242
  redis: regionContext.redis,
1034
1243
  request: safeEval(
1035
1244
  regionContext,
1036
- slidingWindowRemainingTokensScript,
1037
- "getRemainingHash",
1245
+ SCRIPTS.multiRegion.slidingWindow.getRemaining,
1038
1246
  [currentKey, previousKey],
1039
1247
  [now, windowSize]
1040
1248
  // lua seems to return `1` for true and `null` for false
@@ -1054,8 +1262,7 @@ var MultiRegionRatelimit = class extends Ratelimit {
1054
1262
  await Promise.all(ctx.regionContexts.map((regionContext) => {
1055
1263
  safeEval(
1056
1264
  regionContext,
1057
- resetScript,
1058
- "resetHash",
1265
+ RESET_SCRIPT,
1059
1266
  [pattern],
1060
1267
  [null]
1061
1268
  );
@@ -1065,162 +1272,6 @@ var MultiRegionRatelimit = class extends Ratelimit {
1065
1272
  }
1066
1273
  };
1067
1274
 
1068
- // src/lua-scripts/single.ts
1069
- var fixedWindowLimitScript2 = `
1070
- local key = KEYS[1]
1071
- local window = ARGV[1]
1072
- local incrementBy = ARGV[2] -- increment rate per request at a given value, default is 1
1073
-
1074
- local r = redis.call("INCRBY", key, incrementBy)
1075
- if r == tonumber(incrementBy) then
1076
- -- The first time this key is set, the value will be equal to incrementBy.
1077
- -- So we only need the expire command once
1078
- redis.call("PEXPIRE", key, window)
1079
- end
1080
-
1081
- return r
1082
- `;
1083
- var fixedWindowRemainingTokensScript2 = `
1084
- local key = KEYS[1]
1085
- local tokens = 0
1086
-
1087
- local value = redis.call('GET', key)
1088
- if value then
1089
- tokens = value
1090
- end
1091
- return tokens
1092
- `;
1093
- var slidingWindowLimitScript2 = `
1094
- local currentKey = KEYS[1] -- identifier including prefixes
1095
- local previousKey = KEYS[2] -- key of the previous bucket
1096
- local tokens = tonumber(ARGV[1]) -- tokens per window
1097
- local now = ARGV[2] -- current timestamp in milliseconds
1098
- local window = ARGV[3] -- interval in milliseconds
1099
- local incrementBy = ARGV[4] -- increment rate per request at a given value, default is 1
1100
-
1101
- local requestsInCurrentWindow = redis.call("GET", currentKey)
1102
- if requestsInCurrentWindow == false then
1103
- requestsInCurrentWindow = 0
1104
- end
1105
-
1106
- local requestsInPreviousWindow = redis.call("GET", previousKey)
1107
- if requestsInPreviousWindow == false then
1108
- requestsInPreviousWindow = 0
1109
- end
1110
- local percentageInCurrent = ( now % window ) / window
1111
- -- weighted requests to consider from the previous window
1112
- requestsInPreviousWindow = math.floor(( 1 - percentageInCurrent ) * requestsInPreviousWindow)
1113
- if requestsInPreviousWindow + requestsInCurrentWindow >= tokens then
1114
- return -1
1115
- end
1116
-
1117
- local newValue = redis.call("INCRBY", currentKey, incrementBy)
1118
- if newValue == tonumber(incrementBy) then
1119
- -- The first time this key is set, the value will be equal to incrementBy.
1120
- -- So we only need the expire command once
1121
- redis.call("PEXPIRE", currentKey, window * 2 + 1000) -- Enough time to overlap with a new window + 1 second
1122
- end
1123
- return tokens - ( newValue + requestsInPreviousWindow )
1124
- `;
1125
- var slidingWindowRemainingTokensScript2 = `
1126
- local currentKey = KEYS[1] -- identifier including prefixes
1127
- local previousKey = KEYS[2] -- key of the previous bucket
1128
- local now = ARGV[1] -- current timestamp in milliseconds
1129
- local window = ARGV[2] -- interval in milliseconds
1130
-
1131
- local requestsInCurrentWindow = redis.call("GET", currentKey)
1132
- if requestsInCurrentWindow == false then
1133
- requestsInCurrentWindow = 0
1134
- end
1135
-
1136
- local requestsInPreviousWindow = redis.call("GET", previousKey)
1137
- if requestsInPreviousWindow == false then
1138
- requestsInPreviousWindow = 0
1139
- end
1140
-
1141
- local percentageInCurrent = ( now % window ) / window
1142
- -- weighted requests to consider from the previous window
1143
- requestsInPreviousWindow = math.floor(( 1 - percentageInCurrent ) * requestsInPreviousWindow)
1144
-
1145
- return requestsInPreviousWindow + requestsInCurrentWindow
1146
- `;
1147
- var tokenBucketLimitScript = `
1148
- local key = KEYS[1] -- identifier including prefixes
1149
- local maxTokens = tonumber(ARGV[1]) -- maximum number of tokens
1150
- local interval = tonumber(ARGV[2]) -- size of the window in milliseconds
1151
- local refillRate = tonumber(ARGV[3]) -- how many tokens are refilled after each interval
1152
- local now = tonumber(ARGV[4]) -- current timestamp in milliseconds
1153
- local incrementBy = tonumber(ARGV[5]) -- how many tokens to consume, default is 1
1154
-
1155
- local bucket = redis.call("HMGET", key, "refilledAt", "tokens")
1156
-
1157
- local refilledAt
1158
- local tokens
1159
-
1160
- if bucket[1] == false then
1161
- refilledAt = now
1162
- tokens = maxTokens
1163
- else
1164
- refilledAt = tonumber(bucket[1])
1165
- tokens = tonumber(bucket[2])
1166
- end
1167
-
1168
- if now >= refilledAt + interval then
1169
- local numRefills = math.floor((now - refilledAt) / interval)
1170
- tokens = math.min(maxTokens, tokens + numRefills * refillRate)
1171
-
1172
- refilledAt = refilledAt + numRefills * interval
1173
- end
1174
-
1175
- if tokens == 0 then
1176
- return {-1, refilledAt + interval}
1177
- end
1178
-
1179
- local remaining = tokens - incrementBy
1180
- local expireAt = math.ceil(((maxTokens - remaining) / refillRate)) * interval
1181
-
1182
- redis.call("HSET", key, "refilledAt", refilledAt, "tokens", remaining)
1183
- redis.call("PEXPIRE", key, expireAt)
1184
- return {remaining, refilledAt + interval}
1185
- `;
1186
- var tokenBucketIdentifierNotFound = -1;
1187
- var tokenBucketRemainingTokensScript = `
1188
- local key = KEYS[1]
1189
- local maxTokens = tonumber(ARGV[1])
1190
-
1191
- local bucket = redis.call("HMGET", key, "refilledAt", "tokens")
1192
-
1193
- if bucket[1] == false then
1194
- return {maxTokens, ${tokenBucketIdentifierNotFound}}
1195
- end
1196
-
1197
- return {tonumber(bucket[2]), tonumber(bucket[1])}
1198
- `;
1199
- var cachedFixedWindowLimitScript = `
1200
- local key = KEYS[1]
1201
- local window = ARGV[1]
1202
- local incrementBy = ARGV[2] -- increment rate per request at a given value, default is 1
1203
-
1204
- local r = redis.call("INCRBY", key, incrementBy)
1205
- if r == incrementBy then
1206
- -- The first time this key is set, the value will be equal to incrementBy.
1207
- -- So we only need the expire command once
1208
- redis.call("PEXPIRE", key, window)
1209
- end
1210
-
1211
- return r
1212
- `;
1213
- var cachedFixedWindowRemainingTokenScript = `
1214
- local key = KEYS[1]
1215
- local tokens = 0
1216
-
1217
- local value = redis.call('GET', key)
1218
- if value then
1219
- tokens = value
1220
- end
1221
- return tokens
1222
- `;
1223
-
1224
1275
  // src/single.ts
1225
1276
  var RegionRatelimit = class extends Ratelimit {
1226
1277
  /**
@@ -1233,9 +1284,7 @@ var RegionRatelimit = class extends Ratelimit {
1233
1284
  timeout: config.timeout,
1234
1285
  analytics: config.analytics,
1235
1286
  ctx: {
1236
- redis: config.redis,
1237
- scriptHashes: {},
1238
- cacheScripts: config.cacheScripts ?? true
1287
+ redis: config.redis
1239
1288
  },
1240
1289
  ephemeralCache: config.ephemeralCache,
1241
1290
  enableProtection: config.enableProtection,
@@ -1282,8 +1331,7 @@ var RegionRatelimit = class extends Ratelimit {
1282
1331
  const incrementBy = rate ? Math.max(1, rate) : 1;
1283
1332
  const usedTokensAfterUpdate = await safeEval(
1284
1333
  ctx,
1285
- fixedWindowLimitScript2,
1286
- "limitHash",
1334
+ SCRIPTS.singleRegion.fixedWindow.limit,
1287
1335
  [key],
1288
1336
  [windowDuration, incrementBy]
1289
1337
  );
@@ -1306,8 +1354,7 @@ var RegionRatelimit = class extends Ratelimit {
1306
1354
  const key = [identifier, bucket].join(":");
1307
1355
  const usedTokens = await safeEval(
1308
1356
  ctx,
1309
- fixedWindowRemainingTokensScript2,
1310
- "getRemainingHash",
1357
+ SCRIPTS.singleRegion.fixedWindow.getRemaining,
1311
1358
  [key],
1312
1359
  [null]
1313
1360
  );
@@ -1323,8 +1370,7 @@ var RegionRatelimit = class extends Ratelimit {
1323
1370
  }
1324
1371
  await safeEval(
1325
1372
  ctx,
1326
- resetScript,
1327
- "resetHash",
1373
+ RESET_SCRIPT,
1328
1374
  [pattern],
1329
1375
  [null]
1330
1376
  );
@@ -1372,8 +1418,7 @@ var RegionRatelimit = class extends Ratelimit {
1372
1418
  const incrementBy = rate ? Math.max(1, rate) : 1;
1373
1419
  const remainingTokens = await safeEval(
1374
1420
  ctx,
1375
- slidingWindowLimitScript2,
1376
- "limitHash",
1421
+ SCRIPTS.singleRegion.slidingWindow.limit,
1377
1422
  [currentKey, previousKey],
1378
1423
  [tokens, now, windowSize, incrementBy]
1379
1424
  );
@@ -1398,8 +1443,7 @@ var RegionRatelimit = class extends Ratelimit {
1398
1443
  const previousKey = [identifier, previousWindow].join(":");
1399
1444
  const usedTokens = await safeEval(
1400
1445
  ctx,
1401
- slidingWindowRemainingTokensScript2,
1402
- "getRemainingHash",
1446
+ SCRIPTS.singleRegion.slidingWindow.getRemaining,
1403
1447
  [currentKey, previousKey],
1404
1448
  [now, windowSize]
1405
1449
  );
@@ -1415,8 +1459,7 @@ var RegionRatelimit = class extends Ratelimit {
1415
1459
  }
1416
1460
  await safeEval(
1417
1461
  ctx,
1418
- resetScript,
1419
- "resetHash",
1462
+ RESET_SCRIPT,
1420
1463
  [pattern],
1421
1464
  [null]
1422
1465
  );
@@ -1457,8 +1500,7 @@ var RegionRatelimit = class extends Ratelimit {
1457
1500
  const incrementBy = rate ? Math.max(1, rate) : 1;
1458
1501
  const [remaining, reset] = await safeEval(
1459
1502
  ctx,
1460
- tokenBucketLimitScript,
1461
- "limitHash",
1503
+ SCRIPTS.singleRegion.tokenBucket.limit,
1462
1504
  [identifier],
1463
1505
  [maxTokens, intervalDuration, refillRate, now, incrementBy]
1464
1506
  );
@@ -1477,8 +1519,7 @@ var RegionRatelimit = class extends Ratelimit {
1477
1519
  async getRemaining(ctx, identifier) {
1478
1520
  const [remainingTokens, refilledAt] = await safeEval(
1479
1521
  ctx,
1480
- tokenBucketRemainingTokensScript,
1481
- "getRemainingHash",
1522
+ SCRIPTS.singleRegion.tokenBucket.getRemaining,
1482
1523
  [identifier],
1483
1524
  [maxTokens]
1484
1525
  );
@@ -1496,8 +1537,7 @@ var RegionRatelimit = class extends Ratelimit {
1496
1537
  }
1497
1538
  await safeEval(
1498
1539
  ctx,
1499
- resetScript,
1500
- "resetHash",
1540
+ RESET_SCRIPT,
1501
1541
  [pattern],
1502
1542
  [null]
1503
1543
  );
@@ -1545,8 +1585,7 @@ var RegionRatelimit = class extends Ratelimit {
1545
1585
  const success = cachedTokensAfterUpdate < tokens;
1546
1586
  const pending = success ? safeEval(
1547
1587
  ctx,
1548
- cachedFixedWindowLimitScript,
1549
- "limitHash",
1588
+ SCRIPTS.singleRegion.cachedFixedWindow.limit,
1550
1589
  [key],
1551
1590
  [windowDuration, incrementBy]
1552
1591
  ) : Promise.resolve();
@@ -1560,8 +1599,7 @@ var RegionRatelimit = class extends Ratelimit {
1560
1599
  }
1561
1600
  const usedTokensAfterUpdate = await safeEval(
1562
1601
  ctx,
1563
- cachedFixedWindowLimitScript,
1564
- "limitHash",
1602
+ SCRIPTS.singleRegion.cachedFixedWindow.limit,
1565
1603
  [key],
1566
1604
  [windowDuration, incrementBy]
1567
1605
  );
@@ -1591,8 +1629,7 @@ var RegionRatelimit = class extends Ratelimit {
1591
1629
  }
1592
1630
  const usedTokens = await safeEval(
1593
1631
  ctx,
1594
- cachedFixedWindowRemainingTokenScript,
1595
- "getRemainingHash",
1632
+ SCRIPTS.singleRegion.cachedFixedWindow.getRemaining,
1596
1633
  [key],
1597
1634
  [null]
1598
1635
  );
@@ -1611,8 +1648,7 @@ var RegionRatelimit = class extends Ratelimit {
1611
1648
  const pattern = [identifier, "*"].join(":");
1612
1649
  await safeEval(
1613
1650
  ctx,
1614
- resetScript,
1615
- "resetHash",
1651
+ RESET_SCRIPT,
1616
1652
  [pattern],
1617
1653
  [null]
1618
1654
  );