@sapphire/ratelimits 2.4.6-next.78a79ca.0 β 2.4.6-next.7c98509.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 +11 -67
- package/dist/index.global.js +99 -27
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +75 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +70 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -108,70 +108,14 @@ We accept donations through Open Collective, Ko-fi, PayPal, Patreon and GitHub S
|
|
|
108
108
|
| Patreon | [Click Here](https://sapphirejs.dev/patreon) |
|
|
109
109
|
| PayPal | [Click Here](https://sapphirejs.dev/paypal) |
|
|
110
110
|
|
|
111
|
-
## Contributors
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
<td align="center"><a href="https://github.com/PyroTechniac"><img src="https://avatars2.githubusercontent.com/u/39341355?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gryffon Bellish</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=PyroTechniac" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/pulls?q=is%3Apr+reviewed-by%3APyroTechniac" title="Reviewed Pull Requests">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=PyroTechniac" title="Tests">β οΈ</a></td>
|
|
123
|
-
<td align="center"><a href="https://github.com/vladfrangu"><img src="https://avatars3.githubusercontent.com/u/17960496?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vlad Frangu</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=vladfrangu" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/issues?q=author%3Avladfrangu" title="Bug reports">π</a> <a href="https://github.com/sapphiredev/utilities/pulls?q=is%3Apr+reviewed-by%3Avladfrangu" title="Reviewed Pull Requests">π</a> <a href="#userTesting-vladfrangu" title="User Testing">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=vladfrangu" title="Tests">β οΈ</a></td>
|
|
124
|
-
<td align="center"><a href="https://github.com/Stitch07"><img src="https://avatars0.githubusercontent.com/u/29275227?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stitch07</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Stitch07" title="Code">π»</a> <a href="#projectManagement-Stitch07" title="Project Management">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=Stitch07" title="Tests">β οΈ</a></td>
|
|
125
|
-
<td align="center"><a href="https://github.com/apps/depfu"><img src="https://avatars3.githubusercontent.com/in/715?v=4?s=100" width="100px;" alt=""/><br /><sub><b>depfu[bot]</b></sub></a><br /><a href="#maintenance-depfu[bot]" title="Maintenance">π§</a></td>
|
|
126
|
-
<td align="center"><a href="https://github.com/apps/allcontributors"><img src="https://avatars0.githubusercontent.com/in/23186?v=4?s=100" width="100px;" alt=""/><br /><sub><b>allcontributors[bot]</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=allcontributors[bot]" title="Documentation">π</a></td>
|
|
127
|
-
</tr>
|
|
128
|
-
<tr>
|
|
129
|
-
<td align="center"><a href="https://github.com/Nytelife26"><img src="https://avatars1.githubusercontent.com/u/22531310?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tyler J Russell</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Nytelife26" title="Documentation">π</a></td>
|
|
130
|
-
<td align="center"><a href="https://github.com/Alcremie"><img src="https://avatars0.githubusercontent.com/u/54785334?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ivan Lieder</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Alcremie" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/issues?q=author%3AAlcremie" title="Bug reports">π</a></td>
|
|
131
|
-
<td align="center"><a href="https://github.com/RealShadowNova"><img src="https://avatars3.githubusercontent.com/u/46537907?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hezekiah Hendry</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=RealShadowNova" title="Code">π»</a> <a href="#tool-RealShadowNova" title="Tools">π§</a></td>
|
|
132
|
-
<td align="center"><a href="https://github.com/Vetlix"><img src="https://avatars.githubusercontent.com/u/31412314?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vetlix</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Vetlix" title="Code">π»</a></td>
|
|
133
|
-
<td align="center"><a href="https://github.com/ethamitc"><img src="https://avatars.githubusercontent.com/u/27776796?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ethan Mitchell</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=ethamitc" title="Documentation">π</a></td>
|
|
134
|
-
<td align="center"><a href="https://github.com/noftaly"><img src="https://avatars.githubusercontent.com/u/34779161?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Elliot</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=noftaly" title="Code">π»</a></td>
|
|
135
|
-
<td align="center"><a href="https://jurien.dev"><img src="https://avatars.githubusercontent.com/u/5418114?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jurien Hamaker</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=jurienhamaker" title="Code">π»</a></td>
|
|
136
|
-
</tr>
|
|
137
|
-
<tr>
|
|
138
|
-
<td align="center"><a href="https://fanoulis.dev/"><img src="https://avatars.githubusercontent.com/u/38255093?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Charalampos Fanoulis</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=cfanoulis" title="Documentation">π</a></td>
|
|
139
|
-
<td align="center"><a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dependabot[bot]</b></sub></a><br /><a href="#maintenance-dependabot[bot]" title="Maintenance">π§</a></td>
|
|
140
|
-
<td align="center"><a href="https://kaname.netlify.app/"><img src="https://avatars.githubusercontent.com/u/56084970?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kaname</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=kaname-png" title="Code">π»</a></td>
|
|
141
|
-
<td align="center"><a href="https://github.com/nandhagk"><img src="https://avatars.githubusercontent.com/u/62976649?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nandhagk</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/issues?q=author%3Anandhagk" title="Bug reports">π</a></td>
|
|
142
|
-
<td align="center"><a href="https://megatank58.me/"><img src="https://avatars.githubusercontent.com/u/51410502?v=4?s=100" width="100px;" alt=""/><br /><sub><b>megatank58</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=megatank58" title="Code">π»</a></td>
|
|
143
|
-
<td align="center"><a href="https://github.com/UndiedGamer"><img src="https://avatars.githubusercontent.com/u/84702365?v=4?s=100" width="100px;" alt=""/><br /><sub><b>UndiedGamer</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=UndiedGamer" title="Code">π»</a></td>
|
|
144
|
-
<td align="center"><a href="https://github.com/Lioness100"><img src="https://avatars.githubusercontent.com/u/65814829?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lioness100</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Lioness100" title="Documentation">π</a> <a href="https://github.com/sapphiredev/utilities/commits?author=Lioness100" title="Code">π»</a></td>
|
|
145
|
-
</tr>
|
|
146
|
-
<tr>
|
|
147
|
-
<td align="center"><a href="https://gitlab.com/DavidPH/"><img src="https://avatars.githubusercontent.com/u/44669930?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=DavidPHH" title="Code">π»</a></td>
|
|
148
|
-
<td align="center"><a href="https://github.com/apps/renovate"><img src="https://avatars.githubusercontent.com/in/2740?v=4?s=100" width="100px;" alt=""/><br /><sub><b>renovate[bot]</b></sub></a><br /><a href="#maintenance-renovate[bot]" title="Maintenance">π§</a></td>
|
|
149
|
-
<td align="center"><a href="https://renovate.whitesourcesoftware.com/"><img src="https://avatars.githubusercontent.com/u/25180681?v=4?s=100" width="100px;" alt=""/><br /><sub><b>WhiteSource Renovate</b></sub></a><br /><a href="#maintenance-renovate-bot" title="Maintenance">π§</a></td>
|
|
150
|
-
<td align="center"><a href="https://fc5570.me/"><img src="https://avatars.githubusercontent.com/u/68158483?v=4?s=100" width="100px;" alt=""/><br /><sub><b>FC</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=FC5570" title="Code">π»</a></td>
|
|
151
|
-
<td align="center"><a href="https://github.com/Tokipudi"><img src="https://avatars.githubusercontent.com/u/29551076?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JΓ©rΓ©my de Saint Denis</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Tokipudi" title="Code">π»</a></td>
|
|
152
|
-
<td align="center"><a href="https://github.com/ItsMrCube"><img src="https://avatars.githubusercontent.com/u/25201357?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MrCube</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=ItsMrCube" title="Code">π»</a></td>
|
|
153
|
-
<td align="center"><a href="https://github.com/bitomic"><img src="https://avatars.githubusercontent.com/u/35199700?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bitomic</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=bitomic" title="Code">π»</a></td>
|
|
154
|
-
</tr>
|
|
155
|
-
<tr>
|
|
156
|
-
<td align="center"><a href="https://c43721.dev/"><img src="https://avatars.githubusercontent.com/u/55610086?v=4?s=100" width="100px;" alt=""/><br /><sub><b>c43721</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=c43721" title="Code">π»</a></td>
|
|
157
|
-
<td align="center"><a href="https://commandtechno.com/"><img src="https://avatars.githubusercontent.com/u/68407783?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Commandtechno</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Commandtechno" title="Code">π»</a></td>
|
|
158
|
-
<td align="center"><a href="https://github.com/dhruv-kaushikk"><img src="https://avatars.githubusercontent.com/u/73697546?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aura</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=dhruv-kaushikk" title="Code">π»</a></td>
|
|
159
|
-
<td align="center"><a href="https://axis.moe/"><img src="https://avatars.githubusercontent.com/u/54381371?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=axisiscool" title="Code">π»</a></td>
|
|
160
|
-
<td align="center"><a href="https://github.com/imranbarbhuiya"><img src="https://avatars.githubusercontent.com/u/74945038?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Parbez</b></sub></a><br /><a href="#maintenance-imranbarbhuiya" title="Maintenance">π§</a></td>
|
|
161
|
-
<td align="center"><a href="https://github.com/NotKaskus"><img src="https://avatars.githubusercontent.com/u/75168528?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Paul Andrew</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=NotKaskus" title="Documentation">π</a></td>
|
|
162
|
-
<td align="center"><a href="https://linktr.ee/mzato0001"><img src="https://avatars.githubusercontent.com/u/62367547?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mzato</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=Mzato0001" title="Code">π»</a> <a href="https://github.com/sapphiredev/utilities/issues?q=author%3AMzato0001" title="Bug reports">π</a></td>
|
|
163
|
-
</tr>
|
|
164
|
-
<tr>
|
|
165
|
-
<td align="center"><a href="https://github.com/MajesticString"><img src="https://avatars.githubusercontent.com/u/66224939?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Harry Allen</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=MajesticString" title="Documentation">π</a></td>
|
|
166
|
-
<td align="center"><a href="https://github.com/EvolutionX-10"><img src="https://avatars.githubusercontent.com/u/85353424?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Evo</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=EvolutionX-10" title="Code">π»</a></td>
|
|
167
|
-
<td align="center"><a href="https://enes.ovh/"><img src="https://avatars.githubusercontent.com/u/61084101?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Enes GenΓ§</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=enxg" title="Code">π»</a></td>
|
|
168
|
-
<td align="center"><a href="https://github.com/muchnameless"><img src="https://avatars.githubusercontent.com/u/12682826?v=4?s=100" width="100px;" alt=""/><br /><sub><b>muchnameless</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=muchnameless" title="Code">π»</a></td>
|
|
169
|
-
</tr>
|
|
170
|
-
</table>
|
|
171
|
-
|
|
172
|
-
<!-- markdownlint-restore -->
|
|
173
|
-
<!-- prettier-ignore-end -->
|
|
174
|
-
|
|
175
|
-
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
176
|
-
|
|
177
|
-
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
|
111
|
+
## Contributors
|
|
112
|
+
|
|
113
|
+
Please make sure to read the [Contributing Guide][contributing] before making a pull request.
|
|
114
|
+
|
|
115
|
+
Thank you to all the people who already contributed to Sapphire!
|
|
116
|
+
|
|
117
|
+
<a href="https://github.com/sapphiredev/utilities/graphs/contributors">
|
|
118
|
+
<img src="https://contrib.rocks/image?repo=sapphiredev/utilities" />
|
|
119
|
+
</a>
|
|
120
|
+
|
|
121
|
+
[contributing]: https://github.com/sapphiredev/.github/blob/main/.github/CONTRIBUTING.md
|
package/dist/index.global.js
CHANGED
|
@@ -1,54 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
var SapphireRatelimits = (function (exports) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
5
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
6
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
-
var __export = (target, all) => {
|
|
10
|
-
for (var name in all)
|
|
11
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
-
};
|
|
13
|
-
var __copyProps = (to, from, except, desc) => {
|
|
14
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
-
for (let key of __getOwnPropNames(from))
|
|
16
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
-
}
|
|
19
|
-
return to;
|
|
20
|
-
};
|
|
21
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
7
|
var __publicField = (obj, key, value) => {
|
|
23
8
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
24
9
|
return value;
|
|
25
10
|
};
|
|
26
11
|
|
|
27
|
-
// src/index.ts
|
|
28
|
-
var src_exports = {};
|
|
29
|
-
__export(src_exports, {
|
|
30
|
-
RateLimit: () => RateLimit,
|
|
31
|
-
RateLimitManager: () => RateLimitManager
|
|
32
|
-
});
|
|
33
|
-
|
|
34
12
|
// src/lib/RateLimit.ts
|
|
35
13
|
var RateLimit = class {
|
|
14
|
+
/**
|
|
15
|
+
* @param manager The manager for this entry.
|
|
16
|
+
*/
|
|
36
17
|
constructor(manager) {
|
|
18
|
+
/**
|
|
19
|
+
* The remaining amount of times this entry can be dripped before the bucket is empty.
|
|
20
|
+
*/
|
|
37
21
|
__publicField(this, "remaining");
|
|
22
|
+
/**
|
|
23
|
+
* The timestamp that represents when this entry will reset back to a available state.
|
|
24
|
+
*/
|
|
38
25
|
__publicField(this, "expires");
|
|
26
|
+
/**
|
|
27
|
+
* The {@link RateLimitManager} this entry is for.
|
|
28
|
+
*/
|
|
39
29
|
__publicField(this, "manager");
|
|
40
30
|
this.manager = manager;
|
|
41
31
|
this.reset();
|
|
42
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether this entry is expired or not, allowing the bucket to be reset.
|
|
35
|
+
*/
|
|
43
36
|
get expired() {
|
|
44
37
|
return this.remainingTime === 0;
|
|
45
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether this entry is limited or not.
|
|
41
|
+
*/
|
|
46
42
|
get limited() {
|
|
47
43
|
return this.remaining === 0 && !this.expired;
|
|
48
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* The remaining time in milliseconds before resetting.
|
|
47
|
+
*/
|
|
49
48
|
get remainingTime() {
|
|
50
49
|
return Math.max(this.expires - Date.now(), 0);
|
|
51
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Consumes {@link RateLimit.remaining} by one if it's not limited, calling {@link RateLimit.reset} first if {@link RateLimit.expired} is true.
|
|
53
|
+
*/
|
|
52
54
|
consume() {
|
|
53
55
|
if (this.limited)
|
|
54
56
|
throw new Error("Cannot consume a limited bucket");
|
|
@@ -57,13 +59,22 @@ var SapphireRatelimits = (() => {
|
|
|
57
59
|
this.remaining--;
|
|
58
60
|
return this;
|
|
59
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Resets the entry back to it's full state.
|
|
64
|
+
*/
|
|
60
65
|
reset() {
|
|
61
66
|
return this.resetRemaining().resetTime();
|
|
62
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Resets the entry's {@link RateLimit.remaining} uses back to full state.
|
|
70
|
+
*/
|
|
63
71
|
resetRemaining() {
|
|
64
72
|
this.remaining = this.manager.limit;
|
|
65
73
|
return this;
|
|
66
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.
|
|
77
|
+
*/
|
|
67
78
|
resetTime() {
|
|
68
79
|
this.expires = Date.now() + this.manager.time;
|
|
69
80
|
return this;
|
|
@@ -80,6 +91,12 @@ var SapphireRatelimits = (() => {
|
|
|
80
91
|
return value;
|
|
81
92
|
}, "__publicField");
|
|
82
93
|
var TimerManager = /* @__PURE__ */ __name(class extends null {
|
|
94
|
+
/**
|
|
95
|
+
* Creates a timeout gets cleared when destroyed
|
|
96
|
+
* @param fn callback function
|
|
97
|
+
* @param delay amount of time before running the callback
|
|
98
|
+
* @param args additional arguments to pass back to the callback
|
|
99
|
+
*/
|
|
83
100
|
static setTimeout(fn, delay, ...args) {
|
|
84
101
|
const timeout = setTimeout(() => {
|
|
85
102
|
this.storedTimeouts.delete(timeout);
|
|
@@ -88,19 +105,36 @@ var SapphireRatelimits = (() => {
|
|
|
88
105
|
this.storedTimeouts.add(timeout);
|
|
89
106
|
return timeout;
|
|
90
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Clears a timeout created through this class
|
|
110
|
+
* @param timeout The timeout to clear
|
|
111
|
+
*/
|
|
91
112
|
static clearTimeout(timeout) {
|
|
92
113
|
clearTimeout(timeout);
|
|
93
114
|
this.storedTimeouts.delete(timeout);
|
|
94
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Creates an interval gets cleared when destroyed
|
|
118
|
+
* @param fn callback function
|
|
119
|
+
* @param delay amount of time before running the callback
|
|
120
|
+
* @param args additional arguments to pass back to the callback
|
|
121
|
+
*/
|
|
95
122
|
static setInterval(fn, delay, ...args) {
|
|
96
123
|
const interval = setInterval(fn, delay, ...args);
|
|
97
124
|
this.storedIntervals.add(interval);
|
|
98
125
|
return interval;
|
|
99
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Clears an internal created through this class
|
|
129
|
+
* @param interval The interval to clear
|
|
130
|
+
*/
|
|
100
131
|
static clearInterval(interval) {
|
|
101
132
|
clearInterval(interval);
|
|
102
133
|
this.storedIntervals.delete(interval);
|
|
103
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Clears running timeouts and intervals created through this class so NodeJS can gracefully exit
|
|
137
|
+
*/
|
|
104
138
|
static destroy() {
|
|
105
139
|
for (const i of this.storedTimeouts)
|
|
106
140
|
clearTimeout(i);
|
|
@@ -116,26 +150,55 @@ var SapphireRatelimits = (() => {
|
|
|
116
150
|
|
|
117
151
|
// src/lib/RateLimitManager.ts
|
|
118
152
|
var _RateLimitManager = class extends Map {
|
|
153
|
+
/**
|
|
154
|
+
* @param time The amount of milliseconds for the ratelimits from this manager to expire.
|
|
155
|
+
* @param limit The amount of times a {@link RateLimit} can drip before it's limited.
|
|
156
|
+
*/
|
|
119
157
|
constructor(time, limit = 1) {
|
|
120
158
|
super();
|
|
159
|
+
/**
|
|
160
|
+
* The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.
|
|
161
|
+
*/
|
|
121
162
|
__publicField(this, "time");
|
|
163
|
+
/**
|
|
164
|
+
* The amount of times a {@link RateLimit} can drip before it's limited.
|
|
165
|
+
*/
|
|
122
166
|
__publicField(this, "limit");
|
|
167
|
+
/**
|
|
168
|
+
* The interval to sweep expired {@link RateLimit ratelimits}.
|
|
169
|
+
*/
|
|
123
170
|
__publicField(this, "sweepInterval");
|
|
124
171
|
this.time = time;
|
|
125
172
|
this.limit = limit;
|
|
126
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Gets a {@link RateLimit} from this manager or creates it if it does not exist.
|
|
176
|
+
* @param id The id for the {@link RateLimit}
|
|
177
|
+
*/
|
|
127
178
|
acquire(id) {
|
|
128
179
|
return this.get(id) ?? this.create(id);
|
|
129
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Creates a {@link RateLimit} for this manager.
|
|
183
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
184
|
+
*/
|
|
130
185
|
create(id) {
|
|
131
186
|
const value = new RateLimit(this);
|
|
132
187
|
this.set(id, value);
|
|
133
188
|
return value;
|
|
134
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Wraps Collection's set method to set interval to sweep inactive {@link RateLimit}s.
|
|
192
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
193
|
+
* @param value The {@link RateLimit} to set
|
|
194
|
+
*/
|
|
135
195
|
set(id, value) {
|
|
136
196
|
this.sweepInterval ?? (this.sweepInterval = TimerManager.setInterval(this.sweep.bind(this), _RateLimitManager.sweepIntervalDuration));
|
|
137
197
|
return super.set(id, value);
|
|
138
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Wraps Collection's sweep method to clear the interval when this manager is empty.
|
|
201
|
+
*/
|
|
139
202
|
sweep() {
|
|
140
203
|
for (const [id, value] of this.entries()) {
|
|
141
204
|
if (value.expired)
|
|
@@ -149,7 +212,16 @@ var SapphireRatelimits = (() => {
|
|
|
149
212
|
};
|
|
150
213
|
var RateLimitManager = _RateLimitManager;
|
|
151
214
|
__name(RateLimitManager, "RateLimitManager");
|
|
215
|
+
/**
|
|
216
|
+
* The delay in milliseconds for {@link RateLimitManager.sweepInterval}.
|
|
217
|
+
*/
|
|
152
218
|
__publicField(RateLimitManager, "sweepIntervalDuration", 3e4);
|
|
153
|
-
|
|
154
|
-
|
|
219
|
+
|
|
220
|
+
exports.RateLimit = RateLimit;
|
|
221
|
+
exports.RateLimitManager = RateLimitManager;
|
|
222
|
+
|
|
223
|
+
return exports;
|
|
224
|
+
|
|
225
|
+
})({});
|
|
226
|
+
//# sourceMappingURL=out.js.map
|
|
155
227
|
//# sourceMappingURL=index.global.js.map
|
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/
|
|
1
|
+
{"version":3,"sources":["../src/lib/RateLimit.ts","../../timer-manager/src/lib/TimerManager.ts","../src/lib/RateLimitManager.ts"],"names":["__name","__publicField"],"mappings":";;;;;;;;;AAEO,IAAM,YAAN,MAA4B;AAAA;AAAA;AAAA;AAAA,EAmB3B,YAAY,SAA8B;AAfjD;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAQ;AAMP,SAAK,UAAU;AACf,SAAK,MAAM;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,kBAAkB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,cAAc,KAAK,CAAC,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,gBAAwB;AAClC,WAAO,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAAG,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACtB,QAAI,KAAK;AAAS,YAAM,IAAI,MAAM,iCAAiC;AACnE,QAAI,KAAK;AAAS,WAAK,MAAM;AAE7B,SAAK;AACL,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKO,QAAc;AACpB,WAAO,KAAK,eAAe,EAAE,UAAU;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAuB;AAC7B,SAAK,YAAY,KAAK,QAAQ;AAC9B,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKO,YAAkB;AACxB,SAAK,UAAU,KAAK,IAAI,IAAI,KAAK,QAAQ;AACzC,WAAO;AAAA,EACR;AACD;AA9Ea;;;;;;;;;;ACCN,IAAM,eAAN,qCAA2B,KAAK;;;;;;;EAiBtC,OAAc,WAAwB,IAA4B,UAAkB,MAA2B;AAC9G,UAAM,UAAU,WAAW,MAAM;AAChC,WAAK,eAAe,OAAO,OAAO;AAClC,SAAG,GAAG,IAAI;IACX,GAAG,KAAK;AACR,SAAK,eAAe,IAAI,OAAO;AAC/B,WAAO;EACR;;;;;EAMA,OAAc,aAAa,SAA+B;AACzD,iBAAa,OAAO;AACpB,SAAK,eAAe,OAAO,OAAO;EACnC;;;;;;;EAQA,OAAc,YAAyB,IAA4B,UAAkB,MAA2B;AAC/G,UAAM,WAAW,YAAY,IAAI,OAAO,GAAG,IAAI;AAC/C,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO;EACR;;;;;EAMA,OAAc,cAAc,UAAgC;AAC3D,kBAAc,QAAQ;AACtB,SAAK,gBAAgB,OAAO,QAAQ;EACrC;;;;EAKA,OAAc,UAAgB;AAC7B,eAAW,KAAK,KAAK;AAAgB,mBAAa,CAAC;AACnD,eAAW,KAAK,KAAK;AAAiB,oBAAc,CAAC;AACrD,SAAK,eAAe,MAAM;AAC1B,SAAK,gBAAgB,MAAM;EAC5B;AACD,GAjEO;AAAMA,QAAA,cAAA,cAAA;AAIZC,eAJY,cAIG,kBAAiB,oBAAI,IAAoB,CAAA;AAKxDA,eATY,cASG,mBAAkB,oBAAI,IAAoB,CAAA;;;ACTnD,IAAM,oBAAN,cAA2C,IAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAoB/D,YAAY,MAAc,QAAQ,GAAG;AAC3C,UAAM;AAjBP;AAAA;AAAA;AAAA,wBAAgB;AAKhB;AAAA;AAAA;AAAA,wBAAgB;AAKhB;AAAA;AAAA;AAAA,wBAAQ;AASP,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,QAAQ,IAAqB;AACnC,WAAO,KAAK,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,OAAO,IAAqB;AAClC,UAAM,QAAQ,IAAI,UAAU,IAAI;AAChC,SAAK,IAAI,IAAI,KAAK;AAClB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOgB,IAAI,IAAO,OAA2B;AACrD,SAAK,kBAAL,KAAK,gBAAkB,aAAa,YAAY,KAAK,MAAM,KAAK,IAAI,GAAG,kBAAiB,qBAAqB;AAC7G,WAAO,MAAM,IAAI,IAAI,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKO,QAAc;AACpB,eAAW,CAAC,IAAI,KAAK,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAI,MAAM;AAAS,aAAK,OAAO,EAAE;AAAA,IAClC;AAEA,QAAI,KAAK,SAAS,GAAG;AACpB,mBAAa,cAAc,KAAK,aAAc;AAC9C,WAAK,gBAAgB;AAAA,IACtB;AAAA,EACD;AAMD;AAzEO,IAAM,mBAAN;AAAM;AAAA;AAAA;AAAA;AAwEZ,cAxEY,kBAwEE,yBAAwB","sourcesContent":["import type { RateLimitManager } from './RateLimitManager';\n\nexport class RateLimit<K = string> {\n\t/**\n\t * The remaining amount of times this entry can be dripped before the bucket is empty.\n\t */\n\tpublic remaining!: number;\n\n\t/**\n\t * The timestamp that represents when this entry will reset back to a available state.\n\t */\n\tpublic expires!: number;\n\n\t/**\n\t * The {@link RateLimitManager} this entry is for.\n\t */\n\tprivate manager: RateLimitManager<K>;\n\n\t/**\n\t * @param manager The manager for this entry.\n\t */\n\tpublic constructor(manager: RateLimitManager<K>) {\n\t\tthis.manager = manager;\n\t\tthis.reset();\n\t}\n\n\t/**\n\t * Whether this entry is expired or not, allowing the bucket to be reset.\n\t */\n\tpublic get expired(): boolean {\n\t\treturn this.remainingTime === 0;\n\t}\n\n\t/**\n\t * Whether this entry is limited or not.\n\t */\n\tpublic get limited(): boolean {\n\t\treturn this.remaining === 0 && !this.expired;\n\t}\n\n\t/**\n\t * The remaining time in milliseconds before resetting.\n\t */\n\tpublic get remainingTime(): number {\n\t\treturn Math.max(this.expires - Date.now(), 0);\n\t}\n\n\t/**\n\t * Consumes {@link RateLimit.remaining} by one if it's not limited, calling {@link RateLimit.reset} first if {@link RateLimit.expired} is true.\n\t */\n\tpublic consume(): this {\n\t\tif (this.limited) throw new Error('Cannot consume a limited bucket');\n\t\tif (this.expired) this.reset();\n\n\t\tthis.remaining--;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry back to it's full state.\n\t */\n\tpublic reset(): this {\n\t\treturn this.resetRemaining().resetTime();\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.remaining} uses back to full state.\n\t */\n\tpublic resetRemaining(): this {\n\t\tthis.remaining = this.manager.limit;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.\n\t */\n\tpublic resetTime(): this {\n\t\tthis.expires = Date.now() + this.manager.time;\n\t\treturn this;\n\t}\n}\n","/**\n * Manages timers so that this application can be cleanly exited\n */\nexport class TimerManager extends null {\n\t/**\n\t * A set of timeouts to clear on destroy\n\t */\n\tprivate static storedTimeouts = new Set<NodeJS.Timeout>();\n\n\t/**\n\t * A set of intervals to clear on destroy\n\t */\n\tprivate static storedIntervals = new Set<NodeJS.Timeout>();\n\n\t/**\n\t * Creates a timeout gets cleared when destroyed\n\t * @param fn callback function\n\t * @param delay amount of time before running the callback\n\t * @param args additional arguments to pass back to the callback\n\t */\n\tpublic static setTimeout<A = unknown>(fn: (...args: A[]) => void, delay: number, ...args: A[]): NodeJS.Timeout {\n\t\tconst timeout = setTimeout(() => {\n\t\t\tthis.storedTimeouts.delete(timeout);\n\t\t\tfn(...args);\n\t\t}, delay);\n\t\tthis.storedTimeouts.add(timeout);\n\t\treturn timeout;\n\t}\n\n\t/**\n\t * Clears a timeout created through this class\n\t * @param timeout The timeout to clear\n\t */\n\tpublic static clearTimeout(timeout: NodeJS.Timeout): void {\n\t\tclearTimeout(timeout);\n\t\tthis.storedTimeouts.delete(timeout);\n\t}\n\n\t/**\n\t * Creates an interval gets cleared when destroyed\n\t * @param fn callback function\n\t * @param delay amount of time before running the callback\n\t * @param args additional arguments to pass back to the callback\n\t */\n\tpublic static setInterval<A = unknown>(fn: (...args: A[]) => void, delay: number, ...args: A[]): NodeJS.Timeout {\n\t\tconst interval = setInterval(fn, delay, ...args);\n\t\tthis.storedIntervals.add(interval);\n\t\treturn interval;\n\t}\n\n\t/**\n\t * Clears an internal created through this class\n\t * @param interval The interval to clear\n\t */\n\tpublic static clearInterval(interval: NodeJS.Timeout): void {\n\t\tclearInterval(interval);\n\t\tthis.storedIntervals.delete(interval);\n\t}\n\n\t/**\n\t * Clears running timeouts and intervals created through this class so NodeJS can gracefully exit\n\t */\n\tpublic static destroy(): void {\n\t\tfor (const i of this.storedTimeouts) clearTimeout(i);\n\t\tfor (const i of this.storedIntervals) clearInterval(i);\n\t\tthis.storedTimeouts.clear();\n\t\tthis.storedIntervals.clear();\n\t}\n}\n","import { TimerManager } from '@sapphire/timer-manager';\nimport { RateLimit } from './RateLimit';\n\nexport class RateLimitManager<K = string> extends Map<K, RateLimit<K>> {\n\t/**\n\t * The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.\n\t */\n\tpublic readonly time: number;\n\n\t/**\n\t * The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic readonly limit: number;\n\n\t/**\n\t * The interval to sweep expired {@link RateLimit ratelimits}.\n\t */\n\tprivate sweepInterval!: NodeJS.Timer | null;\n\n\t/**\n\t * @param time The amount of milliseconds for the ratelimits from this manager to expire.\n\t * @param limit The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic constructor(time: number, limit = 1) {\n\t\tsuper();\n\n\t\tthis.time = time;\n\t\tthis.limit = limit;\n\t}\n\n\t/**\n\t * Gets a {@link RateLimit} from this manager or creates it if it does not exist.\n\t * @param id The id for the {@link RateLimit}\n\t */\n\tpublic acquire(id: K): RateLimit<K> {\n\t\treturn this.get(id) ?? this.create(id);\n\t}\n\n\t/**\n\t * Creates a {@link RateLimit} for this manager.\n\t * @param id The id the {@link RateLimit} belongs to\n\t */\n\tpublic create(id: K): RateLimit<K> {\n\t\tconst value = new RateLimit(this);\n\t\tthis.set(id, value);\n\t\treturn value;\n\t}\n\n\t/**\n\t * Wraps Collection's set method to set interval to sweep inactive {@link RateLimit}s.\n\t * @param id The id the {@link RateLimit} belongs to\n\t * @param value The {@link RateLimit} to set\n\t */\n\tpublic override set(id: K, value: RateLimit<K>): this {\n\t\tthis.sweepInterval ??= TimerManager.setInterval(this.sweep.bind(this), RateLimitManager.sweepIntervalDuration);\n\t\treturn super.set(id, value);\n\t}\n\n\t/**\n\t * Wraps Collection's sweep method to clear the interval when this manager is empty.\n\t */\n\tpublic sweep(): void {\n\t\tfor (const [id, value] of this.entries()) {\n\t\t\tif (value.expired) this.delete(id);\n\t\t}\n\n\t\tif (this.size === 0) {\n\t\t\tTimerManager.clearInterval(this.sweepInterval!);\n\t\t\tthis.sweepInterval = null;\n\t\t}\n\t}\n\n\t/**\n\t * The delay in milliseconds for {@link RateLimitManager.sweepInterval}.\n\t */\n\tpublic static sweepIntervalDuration = 30_000;\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,55 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var timerManager = require('@sapphire/timer-manager');
|
|
4
|
+
|
|
3
5
|
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
6
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
7
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
-
var __export = (target, all) => {
|
|
10
|
-
for (var name in all)
|
|
11
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
-
};
|
|
13
|
-
var __copyProps = (to, from, except, desc) => {
|
|
14
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
-
for (let key of __getOwnPropNames(from))
|
|
16
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
-
}
|
|
19
|
-
return to;
|
|
20
|
-
};
|
|
21
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
8
|
var __publicField = (obj, key, value) => {
|
|
23
9
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
24
10
|
return value;
|
|
25
11
|
};
|
|
26
12
|
|
|
27
|
-
// src/index.ts
|
|
28
|
-
var src_exports = {};
|
|
29
|
-
__export(src_exports, {
|
|
30
|
-
RateLimit: () => RateLimit,
|
|
31
|
-
RateLimitManager: () => RateLimitManager
|
|
32
|
-
});
|
|
33
|
-
module.exports = __toCommonJS(src_exports);
|
|
34
|
-
|
|
35
13
|
// src/lib/RateLimit.ts
|
|
36
14
|
var RateLimit = class {
|
|
15
|
+
/**
|
|
16
|
+
* @param manager The manager for this entry.
|
|
17
|
+
*/
|
|
37
18
|
constructor(manager) {
|
|
19
|
+
/**
|
|
20
|
+
* The remaining amount of times this entry can be dripped before the bucket is empty.
|
|
21
|
+
*/
|
|
38
22
|
__publicField(this, "remaining");
|
|
23
|
+
/**
|
|
24
|
+
* The timestamp that represents when this entry will reset back to a available state.
|
|
25
|
+
*/
|
|
39
26
|
__publicField(this, "expires");
|
|
27
|
+
/**
|
|
28
|
+
* The {@link RateLimitManager} this entry is for.
|
|
29
|
+
*/
|
|
40
30
|
__publicField(this, "manager");
|
|
41
31
|
this.manager = manager;
|
|
42
32
|
this.reset();
|
|
43
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether this entry is expired or not, allowing the bucket to be reset.
|
|
36
|
+
*/
|
|
44
37
|
get expired() {
|
|
45
38
|
return this.remainingTime === 0;
|
|
46
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Whether this entry is limited or not.
|
|
42
|
+
*/
|
|
47
43
|
get limited() {
|
|
48
44
|
return this.remaining === 0 && !this.expired;
|
|
49
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The remaining time in milliseconds before resetting.
|
|
48
|
+
*/
|
|
50
49
|
get remainingTime() {
|
|
51
50
|
return Math.max(this.expires - Date.now(), 0);
|
|
52
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Consumes {@link RateLimit.remaining} by one if it's not limited, calling {@link RateLimit.reset} first if {@link RateLimit.expired} is true.
|
|
54
|
+
*/
|
|
53
55
|
consume() {
|
|
54
56
|
if (this.limited)
|
|
55
57
|
throw new Error("Cannot consume a limited bucket");
|
|
@@ -58,60 +60,97 @@ var RateLimit = class {
|
|
|
58
60
|
this.remaining--;
|
|
59
61
|
return this;
|
|
60
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Resets the entry back to it's full state.
|
|
65
|
+
*/
|
|
61
66
|
reset() {
|
|
62
67
|
return this.resetRemaining().resetTime();
|
|
63
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Resets the entry's {@link RateLimit.remaining} uses back to full state.
|
|
71
|
+
*/
|
|
64
72
|
resetRemaining() {
|
|
65
73
|
this.remaining = this.manager.limit;
|
|
66
74
|
return this;
|
|
67
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.
|
|
78
|
+
*/
|
|
68
79
|
resetTime() {
|
|
69
80
|
this.expires = Date.now() + this.manager.time;
|
|
70
81
|
return this;
|
|
71
82
|
}
|
|
72
83
|
};
|
|
73
84
|
__name(RateLimit, "RateLimit");
|
|
74
|
-
|
|
75
|
-
// src/lib/RateLimitManager.ts
|
|
76
|
-
var import_timer_manager = require("@sapphire/timer-manager");
|
|
77
85
|
var _RateLimitManager = class extends Map {
|
|
86
|
+
/**
|
|
87
|
+
* @param time The amount of milliseconds for the ratelimits from this manager to expire.
|
|
88
|
+
* @param limit The amount of times a {@link RateLimit} can drip before it's limited.
|
|
89
|
+
*/
|
|
78
90
|
constructor(time, limit = 1) {
|
|
79
91
|
super();
|
|
92
|
+
/**
|
|
93
|
+
* The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.
|
|
94
|
+
*/
|
|
80
95
|
__publicField(this, "time");
|
|
96
|
+
/**
|
|
97
|
+
* The amount of times a {@link RateLimit} can drip before it's limited.
|
|
98
|
+
*/
|
|
81
99
|
__publicField(this, "limit");
|
|
100
|
+
/**
|
|
101
|
+
* The interval to sweep expired {@link RateLimit ratelimits}.
|
|
102
|
+
*/
|
|
82
103
|
__publicField(this, "sweepInterval");
|
|
83
104
|
this.time = time;
|
|
84
105
|
this.limit = limit;
|
|
85
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Gets a {@link RateLimit} from this manager or creates it if it does not exist.
|
|
109
|
+
* @param id The id for the {@link RateLimit}
|
|
110
|
+
*/
|
|
86
111
|
acquire(id) {
|
|
87
112
|
return this.get(id) ?? this.create(id);
|
|
88
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Creates a {@link RateLimit} for this manager.
|
|
116
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
117
|
+
*/
|
|
89
118
|
create(id) {
|
|
90
119
|
const value = new RateLimit(this);
|
|
91
120
|
this.set(id, value);
|
|
92
121
|
return value;
|
|
93
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Wraps Collection's set method to set interval to sweep inactive {@link RateLimit}s.
|
|
125
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
126
|
+
* @param value The {@link RateLimit} to set
|
|
127
|
+
*/
|
|
94
128
|
set(id, value) {
|
|
95
|
-
this.sweepInterval ?? (this.sweepInterval =
|
|
129
|
+
this.sweepInterval ?? (this.sweepInterval = timerManager.TimerManager.setInterval(this.sweep.bind(this), _RateLimitManager.sweepIntervalDuration));
|
|
96
130
|
return super.set(id, value);
|
|
97
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Wraps Collection's sweep method to clear the interval when this manager is empty.
|
|
134
|
+
*/
|
|
98
135
|
sweep() {
|
|
99
136
|
for (const [id, value] of this.entries()) {
|
|
100
137
|
if (value.expired)
|
|
101
138
|
this.delete(id);
|
|
102
139
|
}
|
|
103
140
|
if (this.size === 0) {
|
|
104
|
-
|
|
141
|
+
timerManager.TimerManager.clearInterval(this.sweepInterval);
|
|
105
142
|
this.sweepInterval = null;
|
|
106
143
|
}
|
|
107
144
|
}
|
|
108
145
|
};
|
|
109
146
|
var RateLimitManager = _RateLimitManager;
|
|
110
147
|
__name(RateLimitManager, "RateLimitManager");
|
|
148
|
+
/**
|
|
149
|
+
* The delay in milliseconds for {@link RateLimitManager.sweepInterval}.
|
|
150
|
+
*/
|
|
111
151
|
__publicField(RateLimitManager, "sweepIntervalDuration", 3e4);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
});
|
|
152
|
+
|
|
153
|
+
exports.RateLimit = RateLimit;
|
|
154
|
+
exports.RateLimitManager = RateLimitManager;
|
|
155
|
+
//# sourceMappingURL=out.js.map
|
|
117
156
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/
|
|
1
|
+
{"version":3,"sources":["../src/lib/RateLimit.ts","../src/lib/RateLimitManager.ts"],"names":[],"mappings":";;;;;;;;;AAEO,IAAM,YAAN,MAA4B;AAAA;AAAA;AAAA;AAAA,EAmB3B,YAAY,SAA8B;AAfjD;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAQ;AAMP,SAAK,UAAU;AACf,SAAK,MAAM;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,kBAAkB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,cAAc,KAAK,CAAC,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,gBAAwB;AAClC,WAAO,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAAG,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACtB,QAAI,KAAK;AAAS,YAAM,IAAI,MAAM,iCAAiC;AACnE,QAAI,KAAK;AAAS,WAAK,MAAM;AAE7B,SAAK;AACL,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKO,QAAc;AACpB,WAAO,KAAK,eAAe,EAAE,UAAU;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAuB;AAC7B,SAAK,YAAY,KAAK,QAAQ;AAC9B,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKO,YAAkB;AACxB,SAAK,UAAU,KAAK,IAAI,IAAI,KAAK,QAAQ;AACzC,WAAO;AAAA,EACR;AACD;AA9Ea;;;ACFb,SAAS,oBAAoB;AAGtB,IAAM,oBAAN,cAA2C,IAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAoB/D,YAAY,MAAc,QAAQ,GAAG;AAC3C,UAAM;AAjBP;AAAA;AAAA;AAAA,wBAAgB;AAKhB;AAAA;AAAA;AAAA,wBAAgB;AAKhB;AAAA;AAAA;AAAA,wBAAQ;AASP,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,QAAQ,IAAqB;AACnC,WAAO,KAAK,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,OAAO,IAAqB;AAClC,UAAM,QAAQ,IAAI,UAAU,IAAI;AAChC,SAAK,IAAI,IAAI,KAAK;AAClB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOgB,IAAI,IAAO,OAA2B;AACrD,SAAK,kBAAL,KAAK,gBAAkB,aAAa,YAAY,KAAK,MAAM,KAAK,IAAI,GAAG,kBAAiB,qBAAqB;AAC7G,WAAO,MAAM,IAAI,IAAI,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKO,QAAc;AACpB,eAAW,CAAC,IAAI,KAAK,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAI,MAAM;AAAS,aAAK,OAAO,EAAE;AAAA,IAClC;AAEA,QAAI,KAAK,SAAS,GAAG;AACpB,mBAAa,cAAc,KAAK,aAAc;AAC9C,WAAK,gBAAgB;AAAA,IACtB;AAAA,EACD;AAMD;AAzEO,IAAM,mBAAN;AAAM;AAAA;AAAA;AAAA;AAwEZ,cAxEY,kBAwEE,yBAAwB","sourcesContent":["import type { RateLimitManager } from './RateLimitManager';\n\nexport class RateLimit<K = string> {\n\t/**\n\t * The remaining amount of times this entry can be dripped before the bucket is empty.\n\t */\n\tpublic remaining!: number;\n\n\t/**\n\t * The timestamp that represents when this entry will reset back to a available state.\n\t */\n\tpublic expires!: number;\n\n\t/**\n\t * The {@link RateLimitManager} this entry is for.\n\t */\n\tprivate manager: RateLimitManager<K>;\n\n\t/**\n\t * @param manager The manager for this entry.\n\t */\n\tpublic constructor(manager: RateLimitManager<K>) {\n\t\tthis.manager = manager;\n\t\tthis.reset();\n\t}\n\n\t/**\n\t * Whether this entry is expired or not, allowing the bucket to be reset.\n\t */\n\tpublic get expired(): boolean {\n\t\treturn this.remainingTime === 0;\n\t}\n\n\t/**\n\t * Whether this entry is limited or not.\n\t */\n\tpublic get limited(): boolean {\n\t\treturn this.remaining === 0 && !this.expired;\n\t}\n\n\t/**\n\t * The remaining time in milliseconds before resetting.\n\t */\n\tpublic get remainingTime(): number {\n\t\treturn Math.max(this.expires - Date.now(), 0);\n\t}\n\n\t/**\n\t * Consumes {@link RateLimit.remaining} by one if it's not limited, calling {@link RateLimit.reset} first if {@link RateLimit.expired} is true.\n\t */\n\tpublic consume(): this {\n\t\tif (this.limited) throw new Error('Cannot consume a limited bucket');\n\t\tif (this.expired) this.reset();\n\n\t\tthis.remaining--;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry back to it's full state.\n\t */\n\tpublic reset(): this {\n\t\treturn this.resetRemaining().resetTime();\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.remaining} uses back to full state.\n\t */\n\tpublic resetRemaining(): this {\n\t\tthis.remaining = this.manager.limit;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.\n\t */\n\tpublic resetTime(): this {\n\t\tthis.expires = Date.now() + this.manager.time;\n\t\treturn this;\n\t}\n}\n","import { TimerManager } from '@sapphire/timer-manager';\nimport { RateLimit } from './RateLimit';\n\nexport class RateLimitManager<K = string> extends Map<K, RateLimit<K>> {\n\t/**\n\t * The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.\n\t */\n\tpublic readonly time: number;\n\n\t/**\n\t * The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic readonly limit: number;\n\n\t/**\n\t * The interval to sweep expired {@link RateLimit ratelimits}.\n\t */\n\tprivate sweepInterval!: NodeJS.Timer | null;\n\n\t/**\n\t * @param time The amount of milliseconds for the ratelimits from this manager to expire.\n\t * @param limit The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic constructor(time: number, limit = 1) {\n\t\tsuper();\n\n\t\tthis.time = time;\n\t\tthis.limit = limit;\n\t}\n\n\t/**\n\t * Gets a {@link RateLimit} from this manager or creates it if it does not exist.\n\t * @param id The id for the {@link RateLimit}\n\t */\n\tpublic acquire(id: K): RateLimit<K> {\n\t\treturn this.get(id) ?? this.create(id);\n\t}\n\n\t/**\n\t * Creates a {@link RateLimit} for this manager.\n\t * @param id The id the {@link RateLimit} belongs to\n\t */\n\tpublic create(id: K): RateLimit<K> {\n\t\tconst value = new RateLimit(this);\n\t\tthis.set(id, value);\n\t\treturn value;\n\t}\n\n\t/**\n\t * Wraps Collection's set method to set interval to sweep inactive {@link RateLimit}s.\n\t * @param id The id the {@link RateLimit} belongs to\n\t * @param value The {@link RateLimit} to set\n\t */\n\tpublic override set(id: K, value: RateLimit<K>): this {\n\t\tthis.sweepInterval ??= TimerManager.setInterval(this.sweep.bind(this), RateLimitManager.sweepIntervalDuration);\n\t\treturn super.set(id, value);\n\t}\n\n\t/**\n\t * Wraps Collection's sweep method to clear the interval when this manager is empty.\n\t */\n\tpublic sweep(): void {\n\t\tfor (const [id, value] of this.entries()) {\n\t\t\tif (value.expired) this.delete(id);\n\t\t}\n\n\t\tif (this.size === 0) {\n\t\t\tTimerManager.clearInterval(this.sweepInterval!);\n\t\t\tthis.sweepInterval = null;\n\t\t}\n\t}\n\n\t/**\n\t * The delay in milliseconds for {@link RateLimitManager.sweepInterval}.\n\t */\n\tpublic static sweepIntervalDuration = 30_000;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { TimerManager } from '@sapphire/timer-manager';
|
|
2
|
+
|
|
1
3
|
var __defProp = Object.defineProperty;
|
|
2
4
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
5
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -8,22 +10,46 @@ var __publicField = (obj, key, value) => {
|
|
|
8
10
|
|
|
9
11
|
// src/lib/RateLimit.ts
|
|
10
12
|
var RateLimit = class {
|
|
13
|
+
/**
|
|
14
|
+
* @param manager The manager for this entry.
|
|
15
|
+
*/
|
|
11
16
|
constructor(manager) {
|
|
17
|
+
/**
|
|
18
|
+
* The remaining amount of times this entry can be dripped before the bucket is empty.
|
|
19
|
+
*/
|
|
12
20
|
__publicField(this, "remaining");
|
|
21
|
+
/**
|
|
22
|
+
* The timestamp that represents when this entry will reset back to a available state.
|
|
23
|
+
*/
|
|
13
24
|
__publicField(this, "expires");
|
|
25
|
+
/**
|
|
26
|
+
* The {@link RateLimitManager} this entry is for.
|
|
27
|
+
*/
|
|
14
28
|
__publicField(this, "manager");
|
|
15
29
|
this.manager = manager;
|
|
16
30
|
this.reset();
|
|
17
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Whether this entry is expired or not, allowing the bucket to be reset.
|
|
34
|
+
*/
|
|
18
35
|
get expired() {
|
|
19
36
|
return this.remainingTime === 0;
|
|
20
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether this entry is limited or not.
|
|
40
|
+
*/
|
|
21
41
|
get limited() {
|
|
22
42
|
return this.remaining === 0 && !this.expired;
|
|
23
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* The remaining time in milliseconds before resetting.
|
|
46
|
+
*/
|
|
24
47
|
get remainingTime() {
|
|
25
48
|
return Math.max(this.expires - Date.now(), 0);
|
|
26
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Consumes {@link RateLimit.remaining} by one if it's not limited, calling {@link RateLimit.reset} first if {@link RateLimit.expired} is true.
|
|
52
|
+
*/
|
|
27
53
|
consume() {
|
|
28
54
|
if (this.limited)
|
|
29
55
|
throw new Error("Cannot consume a limited bucket");
|
|
@@ -32,43 +58,78 @@ var RateLimit = class {
|
|
|
32
58
|
this.remaining--;
|
|
33
59
|
return this;
|
|
34
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Resets the entry back to it's full state.
|
|
63
|
+
*/
|
|
35
64
|
reset() {
|
|
36
65
|
return this.resetRemaining().resetTime();
|
|
37
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Resets the entry's {@link RateLimit.remaining} uses back to full state.
|
|
69
|
+
*/
|
|
38
70
|
resetRemaining() {
|
|
39
71
|
this.remaining = this.manager.limit;
|
|
40
72
|
return this;
|
|
41
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.
|
|
76
|
+
*/
|
|
42
77
|
resetTime() {
|
|
43
78
|
this.expires = Date.now() + this.manager.time;
|
|
44
79
|
return this;
|
|
45
80
|
}
|
|
46
81
|
};
|
|
47
82
|
__name(RateLimit, "RateLimit");
|
|
48
|
-
|
|
49
|
-
// src/lib/RateLimitManager.ts
|
|
50
|
-
import { TimerManager } from "@sapphire/timer-manager";
|
|
51
83
|
var _RateLimitManager = class extends Map {
|
|
84
|
+
/**
|
|
85
|
+
* @param time The amount of milliseconds for the ratelimits from this manager to expire.
|
|
86
|
+
* @param limit The amount of times a {@link RateLimit} can drip before it's limited.
|
|
87
|
+
*/
|
|
52
88
|
constructor(time, limit = 1) {
|
|
53
89
|
super();
|
|
90
|
+
/**
|
|
91
|
+
* The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.
|
|
92
|
+
*/
|
|
54
93
|
__publicField(this, "time");
|
|
94
|
+
/**
|
|
95
|
+
* The amount of times a {@link RateLimit} can drip before it's limited.
|
|
96
|
+
*/
|
|
55
97
|
__publicField(this, "limit");
|
|
98
|
+
/**
|
|
99
|
+
* The interval to sweep expired {@link RateLimit ratelimits}.
|
|
100
|
+
*/
|
|
56
101
|
__publicField(this, "sweepInterval");
|
|
57
102
|
this.time = time;
|
|
58
103
|
this.limit = limit;
|
|
59
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Gets a {@link RateLimit} from this manager or creates it if it does not exist.
|
|
107
|
+
* @param id The id for the {@link RateLimit}
|
|
108
|
+
*/
|
|
60
109
|
acquire(id) {
|
|
61
110
|
return this.get(id) ?? this.create(id);
|
|
62
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Creates a {@link RateLimit} for this manager.
|
|
114
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
115
|
+
*/
|
|
63
116
|
create(id) {
|
|
64
117
|
const value = new RateLimit(this);
|
|
65
118
|
this.set(id, value);
|
|
66
119
|
return value;
|
|
67
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Wraps Collection's set method to set interval to sweep inactive {@link RateLimit}s.
|
|
123
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
124
|
+
* @param value The {@link RateLimit} to set
|
|
125
|
+
*/
|
|
68
126
|
set(id, value) {
|
|
69
127
|
this.sweepInterval ?? (this.sweepInterval = TimerManager.setInterval(this.sweep.bind(this), _RateLimitManager.sweepIntervalDuration));
|
|
70
128
|
return super.set(id, value);
|
|
71
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Wraps Collection's sweep method to clear the interval when this manager is empty.
|
|
132
|
+
*/
|
|
72
133
|
sweep() {
|
|
73
134
|
for (const [id, value] of this.entries()) {
|
|
74
135
|
if (value.expired)
|
|
@@ -82,9 +143,11 @@ var _RateLimitManager = class extends Map {
|
|
|
82
143
|
};
|
|
83
144
|
var RateLimitManager = _RateLimitManager;
|
|
84
145
|
__name(RateLimitManager, "RateLimitManager");
|
|
146
|
+
/**
|
|
147
|
+
* The delay in milliseconds for {@link RateLimitManager.sweepInterval}.
|
|
148
|
+
*/
|
|
85
149
|
__publicField(RateLimitManager, "sweepIntervalDuration", 3e4);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
150
|
+
|
|
151
|
+
export { RateLimit, RateLimitManager };
|
|
152
|
+
//# sourceMappingURL=out.js.map
|
|
90
153
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/RateLimit.ts","../src/lib/RateLimitManager.ts"],"sourcesContent":["import type { RateLimitManager } from './RateLimitManager';\n\nexport class RateLimit<K = string> {\n\t/**\n\t * The remaining amount of times this entry can be dripped before the bucket is empty.\n\t */\n\tpublic remaining!: number;\n\n\t/**\n\t * The timestamp that represents when this entry will reset back to a available state.\n\t */\n\tpublic expires!: number;\n\n\t/**\n\t * The {@link RateLimitManager} this entry is for.\n\t */\n\tprivate manager: RateLimitManager<K>;\n\n\t/**\n\t * @param manager The manager for this entry.\n\t */\n\tpublic constructor(manager: RateLimitManager<K>) {\n\t\tthis.manager = manager;\n\t\tthis.reset();\n\t}\n\n\t/**\n\t * Whether this entry is expired or not, allowing the bucket to be reset.\n\t */\n\tpublic get expired(): boolean {\n\t\treturn this.remainingTime === 0;\n\t}\n\n\t/**\n\t * Whether this entry is limited or not.\n\t */\n\tpublic get limited(): boolean {\n\t\treturn this.remaining === 0 && !this.expired;\n\t}\n\n\t/**\n\t * The remaining time in milliseconds before resetting.\n\t */\n\tpublic get remainingTime(): number {\n\t\treturn Math.max(this.expires - Date.now(), 0);\n\t}\n\n\t/**\n\t * Consumes {@link RateLimit.remaining} by one if it's not limited, calling {@link RateLimit.reset} first if {@link RateLimit.expired} is true.\n\t */\n\tpublic consume(): this {\n\t\tif (this.limited) throw new Error('Cannot consume a limited bucket');\n\t\tif (this.expired) this.reset();\n\n\t\tthis.remaining--;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry back to it's full state.\n\t */\n\tpublic reset(): this {\n\t\treturn this.resetRemaining().resetTime();\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.remaining} uses back to full state.\n\t */\n\tpublic resetRemaining(): this {\n\t\tthis.remaining = this.manager.limit;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.\n\t */\n\tpublic resetTime(): this {\n\t\tthis.expires = Date.now() + this.manager.time;\n\t\treturn this;\n\t}\n}\n","import { TimerManager } from '@sapphire/timer-manager';\nimport { RateLimit } from './RateLimit';\n\nexport class RateLimitManager<K = string> extends Map<K, RateLimit<K>> {\n\t/**\n\t * The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.\n\t */\n\tpublic readonly time: number;\n\n\t/**\n\t * The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic readonly limit: number;\n\n\t/**\n\t * The interval to sweep expired {@link RateLimit ratelimits}.\n\t */\n\tprivate sweepInterval!: NodeJS.Timer | null;\n\n\t/**\n\t * @param time The amount of milliseconds for the ratelimits from this manager to expire.\n\t * @param limit The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic constructor(time: number, limit = 1) {\n\t\tsuper();\n\n\t\tthis.time = time;\n\t\tthis.limit = limit;\n\t}\n\n\t/**\n\t * Gets a {@link RateLimit} from this manager or creates it if it does not exist.\n\t * @param id The id for the {@link RateLimit}\n\t */\n\tpublic acquire(id: K): RateLimit<K> {\n\t\treturn this.get(id) ?? this.create(id);\n\t}\n\n\t/**\n\t * Creates a {@link RateLimit} for this manager.\n\t * @param id The id the {@link RateLimit} belongs to\n\t */\n\tpublic create(id: K): RateLimit<K> {\n\t\tconst value = new RateLimit(this);\n\t\tthis.set(id, value);\n\t\treturn value;\n\t}\n\n\t/**\n\t * Wraps Collection's set method to set interval to sweep inactive {@link RateLimit}s.\n\t * @param id The id the {@link RateLimit} belongs to\n\t * @param value The {@link RateLimit} to set\n\t */\n\tpublic override set(id: K, value: RateLimit<K>): this {\n\t\tthis.sweepInterval ??= TimerManager.setInterval(this.sweep.bind(this), RateLimitManager.sweepIntervalDuration);\n\t\treturn super.set(id, value);\n\t}\n\n\t/**\n\t * Wraps Collection's sweep method to clear the interval when this manager is empty.\n\t */\n\tpublic sweep(): void {\n\t\tfor (const [id, value] of this.entries()) {\n\t\t\tif (value.expired) this.delete(id);\n\t\t}\n\n\t\tif (this.size === 0) {\n\t\t\tTimerManager.clearInterval(this.sweepInterval!);\n\t\t\tthis.sweepInterval = null;\n\t\t}\n\t}\n\n\t/**\n\t * The delay in milliseconds for {@link RateLimitManager.sweepInterval}.\n\t */\n\tpublic static sweepIntervalDuration = 30_000;\n}\n"]
|
|
1
|
+
{"version":3,"sources":["../src/lib/RateLimit.ts","../src/lib/RateLimitManager.ts"],"names":[],"mappings":";;;;;;;;;AAEO,IAAM,YAAN,MAA4B;AAAA;AAAA;AAAA;AAAA,EAmB3B,YAAY,SAA8B;AAfjD;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAQ;AAMP,SAAK,UAAU;AACf,SAAK,MAAM;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,kBAAkB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,cAAc,KAAK,CAAC,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,gBAAwB;AAClC,WAAO,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAAG,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACtB,QAAI,KAAK;AAAS,YAAM,IAAI,MAAM,iCAAiC;AACnE,QAAI,KAAK;AAAS,WAAK,MAAM;AAE7B,SAAK;AACL,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKO,QAAc;AACpB,WAAO,KAAK,eAAe,EAAE,UAAU;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAuB;AAC7B,SAAK,YAAY,KAAK,QAAQ;AAC9B,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKO,YAAkB;AACxB,SAAK,UAAU,KAAK,IAAI,IAAI,KAAK,QAAQ;AACzC,WAAO;AAAA,EACR;AACD;AA9Ea;;;ACFb,SAAS,oBAAoB;AAGtB,IAAM,oBAAN,cAA2C,IAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAoB/D,YAAY,MAAc,QAAQ,GAAG;AAC3C,UAAM;AAjBP;AAAA;AAAA;AAAA,wBAAgB;AAKhB;AAAA;AAAA;AAAA,wBAAgB;AAKhB;AAAA;AAAA;AAAA,wBAAQ;AASP,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,QAAQ,IAAqB;AACnC,WAAO,KAAK,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,OAAO,IAAqB;AAClC,UAAM,QAAQ,IAAI,UAAU,IAAI;AAChC,SAAK,IAAI,IAAI,KAAK;AAClB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOgB,IAAI,IAAO,OAA2B;AACrD,SAAK,kBAAL,KAAK,gBAAkB,aAAa,YAAY,KAAK,MAAM,KAAK,IAAI,GAAG,kBAAiB,qBAAqB;AAC7G,WAAO,MAAM,IAAI,IAAI,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKO,QAAc;AACpB,eAAW,CAAC,IAAI,KAAK,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAI,MAAM;AAAS,aAAK,OAAO,EAAE;AAAA,IAClC;AAEA,QAAI,KAAK,SAAS,GAAG;AACpB,mBAAa,cAAc,KAAK,aAAc;AAC9C,WAAK,gBAAgB;AAAA,IACtB;AAAA,EACD;AAMD;AAzEO,IAAM,mBAAN;AAAM;AAAA;AAAA;AAAA;AAwEZ,cAxEY,kBAwEE,yBAAwB","sourcesContent":["import type { RateLimitManager } from './RateLimitManager';\n\nexport class RateLimit<K = string> {\n\t/**\n\t * The remaining amount of times this entry can be dripped before the bucket is empty.\n\t */\n\tpublic remaining!: number;\n\n\t/**\n\t * The timestamp that represents when this entry will reset back to a available state.\n\t */\n\tpublic expires!: number;\n\n\t/**\n\t * The {@link RateLimitManager} this entry is for.\n\t */\n\tprivate manager: RateLimitManager<K>;\n\n\t/**\n\t * @param manager The manager for this entry.\n\t */\n\tpublic constructor(manager: RateLimitManager<K>) {\n\t\tthis.manager = manager;\n\t\tthis.reset();\n\t}\n\n\t/**\n\t * Whether this entry is expired or not, allowing the bucket to be reset.\n\t */\n\tpublic get expired(): boolean {\n\t\treturn this.remainingTime === 0;\n\t}\n\n\t/**\n\t * Whether this entry is limited or not.\n\t */\n\tpublic get limited(): boolean {\n\t\treturn this.remaining === 0 && !this.expired;\n\t}\n\n\t/**\n\t * The remaining time in milliseconds before resetting.\n\t */\n\tpublic get remainingTime(): number {\n\t\treturn Math.max(this.expires - Date.now(), 0);\n\t}\n\n\t/**\n\t * Consumes {@link RateLimit.remaining} by one if it's not limited, calling {@link RateLimit.reset} first if {@link RateLimit.expired} is true.\n\t */\n\tpublic consume(): this {\n\t\tif (this.limited) throw new Error('Cannot consume a limited bucket');\n\t\tif (this.expired) this.reset();\n\n\t\tthis.remaining--;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry back to it's full state.\n\t */\n\tpublic reset(): this {\n\t\treturn this.resetRemaining().resetTime();\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.remaining} uses back to full state.\n\t */\n\tpublic resetRemaining(): this {\n\t\tthis.remaining = this.manager.limit;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.\n\t */\n\tpublic resetTime(): this {\n\t\tthis.expires = Date.now() + this.manager.time;\n\t\treturn this;\n\t}\n}\n","import { TimerManager } from '@sapphire/timer-manager';\nimport { RateLimit } from './RateLimit';\n\nexport class RateLimitManager<K = string> extends Map<K, RateLimit<K>> {\n\t/**\n\t * The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.\n\t */\n\tpublic readonly time: number;\n\n\t/**\n\t * The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic readonly limit: number;\n\n\t/**\n\t * The interval to sweep expired {@link RateLimit ratelimits}.\n\t */\n\tprivate sweepInterval!: NodeJS.Timer | null;\n\n\t/**\n\t * @param time The amount of milliseconds for the ratelimits from this manager to expire.\n\t * @param limit The amount of times a {@link RateLimit} can drip before it's limited.\n\t */\n\tpublic constructor(time: number, limit = 1) {\n\t\tsuper();\n\n\t\tthis.time = time;\n\t\tthis.limit = limit;\n\t}\n\n\t/**\n\t * Gets a {@link RateLimit} from this manager or creates it if it does not exist.\n\t * @param id The id for the {@link RateLimit}\n\t */\n\tpublic acquire(id: K): RateLimit<K> {\n\t\treturn this.get(id) ?? this.create(id);\n\t}\n\n\t/**\n\t * Creates a {@link RateLimit} for this manager.\n\t * @param id The id the {@link RateLimit} belongs to\n\t */\n\tpublic create(id: K): RateLimit<K> {\n\t\tconst value = new RateLimit(this);\n\t\tthis.set(id, value);\n\t\treturn value;\n\t}\n\n\t/**\n\t * Wraps Collection's set method to set interval to sweep inactive {@link RateLimit}s.\n\t * @param id The id the {@link RateLimit} belongs to\n\t * @param value The {@link RateLimit} to set\n\t */\n\tpublic override set(id: K, value: RateLimit<K>): this {\n\t\tthis.sweepInterval ??= TimerManager.setInterval(this.sweep.bind(this), RateLimitManager.sweepIntervalDuration);\n\t\treturn super.set(id, value);\n\t}\n\n\t/**\n\t * Wraps Collection's sweep method to clear the interval when this manager is empty.\n\t */\n\tpublic sweep(): void {\n\t\tfor (const [id, value] of this.entries()) {\n\t\t\tif (value.expired) this.delete(id);\n\t\t}\n\n\t\tif (this.size === 0) {\n\t\t\tTimerManager.clearInterval(this.sweepInterval!);\n\t\t\tthis.sweepInterval = null;\n\t\t}\n\t}\n\n\t/**\n\t * The delay in milliseconds for {@link RateLimitManager.sweepInterval}.\n\t */\n\tpublic static sweepIntervalDuration = 30_000;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sapphire/ratelimits",
|
|
3
|
-
"version": "2.4.6-next.
|
|
3
|
+
"version": "2.4.6-next.7c98509.0",
|
|
4
4
|
"description": "Bucket implementation for Ratelimits.",
|
|
5
5
|
"author": "@sapphire",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
"@sapphire/timer-manager": "^1.0.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@favware/cliff-jumper": "^1.
|
|
63
|
-
"@vitest/coverage-c8": "^0.
|
|
64
|
-
"tsup": "^6.
|
|
65
|
-
"typedoc": "^0.23.
|
|
66
|
-
"typedoc-json-parser": "^
|
|
67
|
-
"typescript": "^4.
|
|
68
|
-
"vitest": "^0.
|
|
62
|
+
"@favware/cliff-jumper": "^1.10.0",
|
|
63
|
+
"@vitest/coverage-c8": "^0.28.4",
|
|
64
|
+
"tsup": "^6.6.0",
|
|
65
|
+
"typedoc": "^0.23.25",
|
|
66
|
+
"typedoc-json-parser": "^7.1.0",
|
|
67
|
+
"typescript": "^4.9.5",
|
|
68
|
+
"vitest": "^0.28.4"
|
|
69
69
|
}
|
|
70
70
|
}
|