@upstash/ratelimit 1.2.1 → 2.0.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/README.md +2 -1
- package/dist/index.d.mts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +43 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +43 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -560,6 +560,14 @@ var Ratelimit = class {
|
|
|
560
560
|
const pattern = [this.prefix, identifier].join(":");
|
|
561
561
|
await this.limiter().resetTokens(this.ctx, pattern);
|
|
562
562
|
};
|
|
563
|
+
/**
|
|
564
|
+
* Returns the remaining token count together with a reset timestamps
|
|
565
|
+
*
|
|
566
|
+
* @param identifier identifir to check
|
|
567
|
+
* @returns object with `remaining` and reset fields. `remaining` denotes
|
|
568
|
+
* the remaining tokens and reset denotes the timestamp when the
|
|
569
|
+
* tokens reset.
|
|
570
|
+
*/
|
|
563
571
|
getRemaining = async (identifier) => {
|
|
564
572
|
const pattern = [this.prefix, identifier].join(":");
|
|
565
573
|
return await this.limiter().getRemaining(this.ctx, pattern);
|
|
@@ -844,7 +852,10 @@ var MultiRegionRatelimit = class extends Ratelimit {
|
|
|
844
852
|
}
|
|
845
853
|
return accTokens + parsedToken;
|
|
846
854
|
}, 0);
|
|
847
|
-
return
|
|
855
|
+
return {
|
|
856
|
+
remaining: Math.max(0, tokens - usedTokens),
|
|
857
|
+
reset: (bucket + 1) * windowDuration
|
|
858
|
+
};
|
|
848
859
|
},
|
|
849
860
|
async resetTokens(ctx, identifier) {
|
|
850
861
|
const pattern = [identifier, "*"].join(":");
|
|
@@ -1006,7 +1017,10 @@ var MultiRegionRatelimit = class extends Ratelimit {
|
|
|
1006
1017
|
)
|
|
1007
1018
|
}));
|
|
1008
1019
|
const usedTokens = await Promise.any(dbs.map((s) => s.request));
|
|
1009
|
-
return
|
|
1020
|
+
return {
|
|
1021
|
+
remaining: Math.max(0, tokens - usedTokens),
|
|
1022
|
+
reset: (currentWindow + 1) * windowSize
|
|
1023
|
+
};
|
|
1010
1024
|
},
|
|
1011
1025
|
async resetTokens(ctx, identifier) {
|
|
1012
1026
|
const pattern = [identifier, "*"].join(":");
|
|
@@ -1145,17 +1159,18 @@ var tokenBucketLimitScript = `
|
|
|
1145
1159
|
redis.call("PEXPIRE", key, expireAt)
|
|
1146
1160
|
return {remaining, refilledAt + interval}
|
|
1147
1161
|
`;
|
|
1162
|
+
var tokenBucketIdentifierNotFound = -1;
|
|
1148
1163
|
var tokenBucketRemainingTokensScript = `
|
|
1149
1164
|
local key = KEYS[1]
|
|
1150
1165
|
local maxTokens = tonumber(ARGV[1])
|
|
1151
1166
|
|
|
1152
|
-
local bucket = redis.call("HMGET", key, "tokens")
|
|
1167
|
+
local bucket = redis.call("HMGET", key, "refilledAt", "tokens")
|
|
1153
1168
|
|
|
1154
1169
|
if bucket[1] == false then
|
|
1155
|
-
return maxTokens
|
|
1170
|
+
return {maxTokens, ${tokenBucketIdentifierNotFound}}
|
|
1156
1171
|
end
|
|
1157
1172
|
|
|
1158
|
-
return tonumber(bucket[1])
|
|
1173
|
+
return {tonumber(bucket[2]), tonumber(bucket[1])}
|
|
1159
1174
|
`;
|
|
1160
1175
|
var cachedFixedWindowLimitScript = `
|
|
1161
1176
|
local key = KEYS[1]
|
|
@@ -1272,7 +1287,10 @@ var RegionRatelimit = class extends Ratelimit {
|
|
|
1272
1287
|
[key],
|
|
1273
1288
|
[null]
|
|
1274
1289
|
);
|
|
1275
|
-
return
|
|
1290
|
+
return {
|
|
1291
|
+
remaining: Math.max(0, tokens - usedTokens),
|
|
1292
|
+
reset: (bucket + 1) * windowDuration
|
|
1293
|
+
};
|
|
1276
1294
|
},
|
|
1277
1295
|
async resetTokens(ctx, identifier) {
|
|
1278
1296
|
const pattern = [identifier, "*"].join(":");
|
|
@@ -1361,7 +1379,10 @@ var RegionRatelimit = class extends Ratelimit {
|
|
|
1361
1379
|
[currentKey, previousKey],
|
|
1362
1380
|
[now, windowSize]
|
|
1363
1381
|
);
|
|
1364
|
-
return
|
|
1382
|
+
return {
|
|
1383
|
+
remaining: Math.max(0, tokens - usedTokens),
|
|
1384
|
+
reset: (currentWindow + 1) * windowSize
|
|
1385
|
+
};
|
|
1365
1386
|
},
|
|
1366
1387
|
async resetTokens(ctx, identifier) {
|
|
1367
1388
|
const pattern = [identifier, "*"].join(":");
|
|
@@ -1430,14 +1451,19 @@ var RegionRatelimit = class extends Ratelimit {
|
|
|
1430
1451
|
};
|
|
1431
1452
|
},
|
|
1432
1453
|
async getRemaining(ctx, identifier) {
|
|
1433
|
-
const remainingTokens = await safeEval(
|
|
1454
|
+
const [remainingTokens, refilledAt] = await safeEval(
|
|
1434
1455
|
ctx,
|
|
1435
1456
|
tokenBucketRemainingTokensScript,
|
|
1436
1457
|
"getRemainingHash",
|
|
1437
1458
|
[identifier],
|
|
1438
1459
|
[maxTokens]
|
|
1439
1460
|
);
|
|
1440
|
-
|
|
1461
|
+
const freshRefillAt = Date.now() + intervalDuration;
|
|
1462
|
+
const identifierRefillsAt = refilledAt + intervalDuration;
|
|
1463
|
+
return {
|
|
1464
|
+
remaining: remainingTokens,
|
|
1465
|
+
reset: refilledAt === tokenBucketIdentifierNotFound ? freshRefillAt : identifierRefillsAt
|
|
1466
|
+
};
|
|
1441
1467
|
},
|
|
1442
1468
|
async resetTokens(ctx, identifier) {
|
|
1443
1469
|
const pattern = identifier;
|
|
@@ -1534,7 +1560,10 @@ var RegionRatelimit = class extends Ratelimit {
|
|
|
1534
1560
|
const hit = typeof ctx.cache.get(key) === "number";
|
|
1535
1561
|
if (hit) {
|
|
1536
1562
|
const cachedUsedTokens = ctx.cache.get(key) ?? 0;
|
|
1537
|
-
return
|
|
1563
|
+
return {
|
|
1564
|
+
remaining: Math.max(0, tokens - cachedUsedTokens),
|
|
1565
|
+
reset: (bucket + 1) * windowDuration
|
|
1566
|
+
};
|
|
1538
1567
|
}
|
|
1539
1568
|
const usedTokens = await safeEval(
|
|
1540
1569
|
ctx,
|
|
@@ -1543,7 +1572,10 @@ var RegionRatelimit = class extends Ratelimit {
|
|
|
1543
1572
|
[key],
|
|
1544
1573
|
[null]
|
|
1545
1574
|
);
|
|
1546
|
-
return
|
|
1575
|
+
return {
|
|
1576
|
+
remaining: Math.max(0, tokens - usedTokens),
|
|
1577
|
+
reset: (bucket + 1) * windowDuration
|
|
1578
|
+
};
|
|
1547
1579
|
},
|
|
1548
1580
|
async resetTokens(ctx, identifier) {
|
|
1549
1581
|
if (!ctx.cache) {
|