@sapphire/ratelimits 2.4.6-next.cd98c48.0 β 2.4.6-next.cf249ce.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 -75
- package/dist/index.global.js +88 -0
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -108,78 +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
|
-
<td align="center"><a href="https://github.com/r-priyam"><img src="https://avatars.githubusercontent.com/u/50884372?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Priyam</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=r-priyam" title="Code">π»</a></td>
|
|
170
|
-
<td align="center"><a href="https://github.com/legendhimslef"><img src="https://avatars.githubusercontent.com/u/69213593?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Voxelli</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=legendhimslef" title="Code">π»</a></td>
|
|
171
|
-
<td align="center"><a href="https://github.com/CitTheDev"><img src="https://avatars.githubusercontent.com/u/94020875?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cit The Dev</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=CitTheDev" title="Code">π»</a></td>
|
|
172
|
-
</tr>
|
|
173
|
-
<tr>
|
|
174
|
-
<td align="center"><a href="https://www.goestav.com/"><img src="https://avatars.githubusercontent.com/u/27970303?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Goestav</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=goestav" title="Code">π»</a></td>
|
|
175
|
-
<td align="center"><a href="https://github.com/didinele"><img src="https://avatars.githubusercontent.com/u/27137376?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DD</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=didinele" title="Code">π»</a></td>
|
|
176
|
-
<td align="center"><a href="https://steamcommunity.com/id/06000208"><img src="https://avatars.githubusercontent.com/u/52764066?v=4?s=100" width="100px;" alt=""/><br /><sub><b>amber</b></sub></a><br /><a href="https://github.com/sapphiredev/utilities/commits?author=06000208" title="Code">π»</a></td>
|
|
177
|
-
</tr>
|
|
178
|
-
</table>
|
|
179
|
-
|
|
180
|
-
<!-- markdownlint-restore -->
|
|
181
|
-
<!-- prettier-ignore-end -->
|
|
182
|
-
|
|
183
|
-
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
184
|
-
|
|
185
|
-
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
|
@@ -11,22 +11,46 @@ var SapphireRatelimits = (function (exports) {
|
|
|
11
11
|
|
|
12
12
|
// src/lib/RateLimit.ts
|
|
13
13
|
var RateLimit = class {
|
|
14
|
+
/**
|
|
15
|
+
* @param manager The manager for this entry.
|
|
16
|
+
*/
|
|
14
17
|
constructor(manager) {
|
|
18
|
+
/**
|
|
19
|
+
* The remaining amount of times this entry can be dripped before the bucket is empty.
|
|
20
|
+
*/
|
|
15
21
|
__publicField(this, "remaining");
|
|
22
|
+
/**
|
|
23
|
+
* The timestamp that represents when this entry will reset back to a available state.
|
|
24
|
+
*/
|
|
16
25
|
__publicField(this, "expires");
|
|
26
|
+
/**
|
|
27
|
+
* The {@link RateLimitManager} this entry is for.
|
|
28
|
+
*/
|
|
17
29
|
__publicField(this, "manager");
|
|
18
30
|
this.manager = manager;
|
|
19
31
|
this.reset();
|
|
20
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether this entry is expired or not, allowing the bucket to be reset.
|
|
35
|
+
*/
|
|
21
36
|
get expired() {
|
|
22
37
|
return this.remainingTime === 0;
|
|
23
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether this entry is limited or not.
|
|
41
|
+
*/
|
|
24
42
|
get limited() {
|
|
25
43
|
return this.remaining === 0 && !this.expired;
|
|
26
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* The remaining time in milliseconds before resetting.
|
|
47
|
+
*/
|
|
27
48
|
get remainingTime() {
|
|
28
49
|
return Math.max(this.expires - Date.now(), 0);
|
|
29
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
|
+
*/
|
|
30
54
|
consume() {
|
|
31
55
|
if (this.limited)
|
|
32
56
|
throw new Error("Cannot consume a limited bucket");
|
|
@@ -35,13 +59,22 @@ var SapphireRatelimits = (function (exports) {
|
|
|
35
59
|
this.remaining--;
|
|
36
60
|
return this;
|
|
37
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Resets the entry back to it's full state.
|
|
64
|
+
*/
|
|
38
65
|
reset() {
|
|
39
66
|
return this.resetRemaining().resetTime();
|
|
40
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Resets the entry's {@link RateLimit.remaining} uses back to full state.
|
|
70
|
+
*/
|
|
41
71
|
resetRemaining() {
|
|
42
72
|
this.remaining = this.manager.limit;
|
|
43
73
|
return this;
|
|
44
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.
|
|
77
|
+
*/
|
|
45
78
|
resetTime() {
|
|
46
79
|
this.expires = Date.now() + this.manager.time;
|
|
47
80
|
return this;
|
|
@@ -58,6 +91,12 @@ var SapphireRatelimits = (function (exports) {
|
|
|
58
91
|
return value;
|
|
59
92
|
}, "__publicField");
|
|
60
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
|
+
*/
|
|
61
100
|
static setTimeout(fn, delay, ...args) {
|
|
62
101
|
const timeout = setTimeout(() => {
|
|
63
102
|
this.storedTimeouts.delete(timeout);
|
|
@@ -66,19 +105,36 @@ var SapphireRatelimits = (function (exports) {
|
|
|
66
105
|
this.storedTimeouts.add(timeout);
|
|
67
106
|
return timeout;
|
|
68
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Clears a timeout created through this class
|
|
110
|
+
* @param timeout The timeout to clear
|
|
111
|
+
*/
|
|
69
112
|
static clearTimeout(timeout) {
|
|
70
113
|
clearTimeout(timeout);
|
|
71
114
|
this.storedTimeouts.delete(timeout);
|
|
72
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
|
+
*/
|
|
73
122
|
static setInterval(fn, delay, ...args) {
|
|
74
123
|
const interval = setInterval(fn, delay, ...args);
|
|
75
124
|
this.storedIntervals.add(interval);
|
|
76
125
|
return interval;
|
|
77
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Clears an internal created through this class
|
|
129
|
+
* @param interval The interval to clear
|
|
130
|
+
*/
|
|
78
131
|
static clearInterval(interval) {
|
|
79
132
|
clearInterval(interval);
|
|
80
133
|
this.storedIntervals.delete(interval);
|
|
81
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Clears running timeouts and intervals created through this class so NodeJS can gracefully exit
|
|
137
|
+
*/
|
|
82
138
|
static destroy() {
|
|
83
139
|
for (const i of this.storedTimeouts)
|
|
84
140
|
clearTimeout(i);
|
|
@@ -94,26 +150,55 @@ var SapphireRatelimits = (function (exports) {
|
|
|
94
150
|
|
|
95
151
|
// src/lib/RateLimitManager.ts
|
|
96
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
|
+
*/
|
|
97
157
|
constructor(time, limit = 1) {
|
|
98
158
|
super();
|
|
159
|
+
/**
|
|
160
|
+
* The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.
|
|
161
|
+
*/
|
|
99
162
|
__publicField(this, "time");
|
|
163
|
+
/**
|
|
164
|
+
* The amount of times a {@link RateLimit} can drip before it's limited.
|
|
165
|
+
*/
|
|
100
166
|
__publicField(this, "limit");
|
|
167
|
+
/**
|
|
168
|
+
* The interval to sweep expired {@link RateLimit ratelimits}.
|
|
169
|
+
*/
|
|
101
170
|
__publicField(this, "sweepInterval");
|
|
102
171
|
this.time = time;
|
|
103
172
|
this.limit = limit;
|
|
104
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
|
+
*/
|
|
105
178
|
acquire(id) {
|
|
106
179
|
return this.get(id) ?? this.create(id);
|
|
107
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Creates a {@link RateLimit} for this manager.
|
|
183
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
184
|
+
*/
|
|
108
185
|
create(id) {
|
|
109
186
|
const value = new RateLimit(this);
|
|
110
187
|
this.set(id, value);
|
|
111
188
|
return value;
|
|
112
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
|
+
*/
|
|
113
195
|
set(id, value) {
|
|
114
196
|
this.sweepInterval ?? (this.sweepInterval = TimerManager.setInterval(this.sweep.bind(this), _RateLimitManager.sweepIntervalDuration));
|
|
115
197
|
return super.set(id, value);
|
|
116
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Wraps Collection's sweep method to clear the interval when this manager is empty.
|
|
201
|
+
*/
|
|
117
202
|
sweep() {
|
|
118
203
|
for (const [id, value] of this.entries()) {
|
|
119
204
|
if (value.expired)
|
|
@@ -127,6 +212,9 @@ var SapphireRatelimits = (function (exports) {
|
|
|
127
212
|
};
|
|
128
213
|
var RateLimitManager = _RateLimitManager;
|
|
129
214
|
__name(RateLimitManager, "RateLimitManager");
|
|
215
|
+
/**
|
|
216
|
+
* The delay in milliseconds for {@link RateLimitManager.sweepInterval}.
|
|
217
|
+
*/
|
|
130
218
|
__publicField(RateLimitManager, "sweepIntervalDuration", 3e4);
|
|
131
219
|
|
|
132
220
|
exports.RateLimit = RateLimit;
|
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,EAmB3B,YAAY,SAA8B;AAfjD,wBAAO;AAKP,wBAAO;AAKP,wBAAQ;AAMP,SAAK,UAAU;AACf,SAAK,MAAM;AAAA,EACZ;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,kBAAkB;AAAA,EAC/B;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,cAAc,KAAK,CAAC,KAAK;AAAA,EACtC;AAAA,EAKA,IAAW,gBAAwB;AAClC,WAAO,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAAG,CAAC;AAAA,EAC7C;AAAA,EAKO,UAAgB;AACtB,QAAI,KAAK;AAAS,YAAM,IAAI,MAAM,iCAAiC;AACnE,QAAI,KAAK;AAAS,WAAK,MAAM;AAE7B,SAAK;AACL,WAAO;AAAA,EACR;AAAA,EAKO,QAAc;AACpB,WAAO,KAAK,eAAe,EAAE,UAAU;AAAA,EACxC;AAAA,EAKO,iBAAuB;AAC7B,SAAK,YAAY,KAAK,QAAQ;AAC9B,WAAO;AAAA,EACR;AAAA,EAKO,YAAkB;AACxB,SAAK,UAAU,KAAK,IAAI,IAAI,KAAK,QAAQ;AACzC,WAAO;AAAA,EACR;AACD;AA9Ea;;;;;;;;;;ACCN,IAAM,eAAN,qCAA2B,KAAK
|
|
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
|
@@ -12,22 +12,46 @@ var __publicField = (obj, key, value) => {
|
|
|
12
12
|
|
|
13
13
|
// src/lib/RateLimit.ts
|
|
14
14
|
var RateLimit = class {
|
|
15
|
+
/**
|
|
16
|
+
* @param manager The manager for this entry.
|
|
17
|
+
*/
|
|
15
18
|
constructor(manager) {
|
|
19
|
+
/**
|
|
20
|
+
* The remaining amount of times this entry can be dripped before the bucket is empty.
|
|
21
|
+
*/
|
|
16
22
|
__publicField(this, "remaining");
|
|
23
|
+
/**
|
|
24
|
+
* The timestamp that represents when this entry will reset back to a available state.
|
|
25
|
+
*/
|
|
17
26
|
__publicField(this, "expires");
|
|
27
|
+
/**
|
|
28
|
+
* The {@link RateLimitManager} this entry is for.
|
|
29
|
+
*/
|
|
18
30
|
__publicField(this, "manager");
|
|
19
31
|
this.manager = manager;
|
|
20
32
|
this.reset();
|
|
21
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether this entry is expired or not, allowing the bucket to be reset.
|
|
36
|
+
*/
|
|
22
37
|
get expired() {
|
|
23
38
|
return this.remainingTime === 0;
|
|
24
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Whether this entry is limited or not.
|
|
42
|
+
*/
|
|
25
43
|
get limited() {
|
|
26
44
|
return this.remaining === 0 && !this.expired;
|
|
27
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The remaining time in milliseconds before resetting.
|
|
48
|
+
*/
|
|
28
49
|
get remainingTime() {
|
|
29
50
|
return Math.max(this.expires - Date.now(), 0);
|
|
30
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
|
+
*/
|
|
31
55
|
consume() {
|
|
32
56
|
if (this.limited)
|
|
33
57
|
throw new Error("Cannot consume a limited bucket");
|
|
@@ -36,13 +60,22 @@ var RateLimit = class {
|
|
|
36
60
|
this.remaining--;
|
|
37
61
|
return this;
|
|
38
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Resets the entry back to it's full state.
|
|
65
|
+
*/
|
|
39
66
|
reset() {
|
|
40
67
|
return this.resetRemaining().resetTime();
|
|
41
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Resets the entry's {@link RateLimit.remaining} uses back to full state.
|
|
71
|
+
*/
|
|
42
72
|
resetRemaining() {
|
|
43
73
|
this.remaining = this.manager.limit;
|
|
44
74
|
return this;
|
|
45
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.
|
|
78
|
+
*/
|
|
46
79
|
resetTime() {
|
|
47
80
|
this.expires = Date.now() + this.manager.time;
|
|
48
81
|
return this;
|
|
@@ -50,26 +83,55 @@ var RateLimit = class {
|
|
|
50
83
|
};
|
|
51
84
|
__name(RateLimit, "RateLimit");
|
|
52
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
|
+
*/
|
|
53
90
|
constructor(time, limit = 1) {
|
|
54
91
|
super();
|
|
92
|
+
/**
|
|
93
|
+
* The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.
|
|
94
|
+
*/
|
|
55
95
|
__publicField(this, "time");
|
|
96
|
+
/**
|
|
97
|
+
* The amount of times a {@link RateLimit} can drip before it's limited.
|
|
98
|
+
*/
|
|
56
99
|
__publicField(this, "limit");
|
|
100
|
+
/**
|
|
101
|
+
* The interval to sweep expired {@link RateLimit ratelimits}.
|
|
102
|
+
*/
|
|
57
103
|
__publicField(this, "sweepInterval");
|
|
58
104
|
this.time = time;
|
|
59
105
|
this.limit = limit;
|
|
60
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
|
+
*/
|
|
61
111
|
acquire(id) {
|
|
62
112
|
return this.get(id) ?? this.create(id);
|
|
63
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Creates a {@link RateLimit} for this manager.
|
|
116
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
117
|
+
*/
|
|
64
118
|
create(id) {
|
|
65
119
|
const value = new RateLimit(this);
|
|
66
120
|
this.set(id, value);
|
|
67
121
|
return value;
|
|
68
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
|
+
*/
|
|
69
128
|
set(id, value) {
|
|
70
129
|
this.sweepInterval ?? (this.sweepInterval = timerManager.TimerManager.setInterval(this.sweep.bind(this), _RateLimitManager.sweepIntervalDuration));
|
|
71
130
|
return super.set(id, value);
|
|
72
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Wraps Collection's sweep method to clear the interval when this manager is empty.
|
|
134
|
+
*/
|
|
73
135
|
sweep() {
|
|
74
136
|
for (const [id, value] of this.entries()) {
|
|
75
137
|
if (value.expired)
|
|
@@ -83,6 +145,9 @@ var _RateLimitManager = class extends Map {
|
|
|
83
145
|
};
|
|
84
146
|
var RateLimitManager = _RateLimitManager;
|
|
85
147
|
__name(RateLimitManager, "RateLimitManager");
|
|
148
|
+
/**
|
|
149
|
+
* The delay in milliseconds for {@link RateLimitManager.sweepInterval}.
|
|
150
|
+
*/
|
|
86
151
|
__publicField(RateLimitManager, "sweepIntervalDuration", 3e4);
|
|
87
152
|
|
|
88
153
|
exports.RateLimit = RateLimit;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/RateLimit.ts","../src/lib/RateLimitManager.ts"],"names":[],"mappings":";;;;;;;;;AAEO,IAAM,YAAN,MAA4B;AAAA,EAmB3B,YAAY,SAA8B;AAfjD,wBAAO;AAKP,wBAAO;AAKP,wBAAQ;AAMP,SAAK,UAAU;AACf,SAAK,MAAM;AAAA,EACZ;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,kBAAkB;AAAA,EAC/B;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,cAAc,KAAK,CAAC,KAAK;AAAA,EACtC;AAAA,EAKA,IAAW,gBAAwB;AAClC,WAAO,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAAG,CAAC;AAAA,EAC7C;AAAA,EAKO,UAAgB;AACtB,QAAI,KAAK;AAAS,YAAM,IAAI,MAAM,iCAAiC;AACnE,QAAI,KAAK;AAAS,WAAK,MAAM;AAE7B,SAAK;AACL,WAAO;AAAA,EACR;AAAA,EAKO,QAAc;AACpB,WAAO,KAAK,eAAe,EAAE,UAAU;AAAA,EACxC;AAAA,EAKO,iBAAuB;AAC7B,SAAK,YAAY,KAAK,QAAQ;AAC9B,WAAO;AAAA,EACR;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,EAoB/D,YAAY,MAAc,QAAQ,GAAG;AAC3C,UAAM;AAjBP,wBAAgB;AAKhB,wBAAgB;AAKhB,wBAAQ;AASP,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACd;AAAA,EAMO,QAAQ,IAAqB;AACnC,WAAO,KAAK,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE;AAAA,EACtC;AAAA,EAMO,OAAO,IAAqB;AAClC,UAAM,QAAQ,IAAI,UAAU,IAAI;AAChC,SAAK,IAAI,IAAI,KAAK;AAClB,WAAO;AAAA,EACR;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,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;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"]}
|
|
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
|
@@ -10,22 +10,46 @@ var __publicField = (obj, key, value) => {
|
|
|
10
10
|
|
|
11
11
|
// src/lib/RateLimit.ts
|
|
12
12
|
var RateLimit = class {
|
|
13
|
+
/**
|
|
14
|
+
* @param manager The manager for this entry.
|
|
15
|
+
*/
|
|
13
16
|
constructor(manager) {
|
|
17
|
+
/**
|
|
18
|
+
* The remaining amount of times this entry can be dripped before the bucket is empty.
|
|
19
|
+
*/
|
|
14
20
|
__publicField(this, "remaining");
|
|
21
|
+
/**
|
|
22
|
+
* The timestamp that represents when this entry will reset back to a available state.
|
|
23
|
+
*/
|
|
15
24
|
__publicField(this, "expires");
|
|
25
|
+
/**
|
|
26
|
+
* The {@link RateLimitManager} this entry is for.
|
|
27
|
+
*/
|
|
16
28
|
__publicField(this, "manager");
|
|
17
29
|
this.manager = manager;
|
|
18
30
|
this.reset();
|
|
19
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Whether this entry is expired or not, allowing the bucket to be reset.
|
|
34
|
+
*/
|
|
20
35
|
get expired() {
|
|
21
36
|
return this.remainingTime === 0;
|
|
22
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether this entry is limited or not.
|
|
40
|
+
*/
|
|
23
41
|
get limited() {
|
|
24
42
|
return this.remaining === 0 && !this.expired;
|
|
25
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* The remaining time in milliseconds before resetting.
|
|
46
|
+
*/
|
|
26
47
|
get remainingTime() {
|
|
27
48
|
return Math.max(this.expires - Date.now(), 0);
|
|
28
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
|
+
*/
|
|
29
53
|
consume() {
|
|
30
54
|
if (this.limited)
|
|
31
55
|
throw new Error("Cannot consume a limited bucket");
|
|
@@ -34,13 +58,22 @@ var RateLimit = class {
|
|
|
34
58
|
this.remaining--;
|
|
35
59
|
return this;
|
|
36
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Resets the entry back to it's full state.
|
|
63
|
+
*/
|
|
37
64
|
reset() {
|
|
38
65
|
return this.resetRemaining().resetTime();
|
|
39
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Resets the entry's {@link RateLimit.remaining} uses back to full state.
|
|
69
|
+
*/
|
|
40
70
|
resetRemaining() {
|
|
41
71
|
this.remaining = this.manager.limit;
|
|
42
72
|
return this;
|
|
43
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Resets the entry's {@link RateLimit.expires} to the current time plus {@link RateLimitManager.time}.
|
|
76
|
+
*/
|
|
44
77
|
resetTime() {
|
|
45
78
|
this.expires = Date.now() + this.manager.time;
|
|
46
79
|
return this;
|
|
@@ -48,26 +81,55 @@ var RateLimit = class {
|
|
|
48
81
|
};
|
|
49
82
|
__name(RateLimit, "RateLimit");
|
|
50
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
|
+
*/
|
|
51
88
|
constructor(time, limit = 1) {
|
|
52
89
|
super();
|
|
90
|
+
/**
|
|
91
|
+
* The amount of milliseconds for the {@link RateLimit ratelimits} from this manager to expire.
|
|
92
|
+
*/
|
|
53
93
|
__publicField(this, "time");
|
|
94
|
+
/**
|
|
95
|
+
* The amount of times a {@link RateLimit} can drip before it's limited.
|
|
96
|
+
*/
|
|
54
97
|
__publicField(this, "limit");
|
|
98
|
+
/**
|
|
99
|
+
* The interval to sweep expired {@link RateLimit ratelimits}.
|
|
100
|
+
*/
|
|
55
101
|
__publicField(this, "sweepInterval");
|
|
56
102
|
this.time = time;
|
|
57
103
|
this.limit = limit;
|
|
58
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
|
+
*/
|
|
59
109
|
acquire(id) {
|
|
60
110
|
return this.get(id) ?? this.create(id);
|
|
61
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Creates a {@link RateLimit} for this manager.
|
|
114
|
+
* @param id The id the {@link RateLimit} belongs to
|
|
115
|
+
*/
|
|
62
116
|
create(id) {
|
|
63
117
|
const value = new RateLimit(this);
|
|
64
118
|
this.set(id, value);
|
|
65
119
|
return value;
|
|
66
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
|
+
*/
|
|
67
126
|
set(id, value) {
|
|
68
127
|
this.sweepInterval ?? (this.sweepInterval = TimerManager.setInterval(this.sweep.bind(this), _RateLimitManager.sweepIntervalDuration));
|
|
69
128
|
return super.set(id, value);
|
|
70
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Wraps Collection's sweep method to clear the interval when this manager is empty.
|
|
132
|
+
*/
|
|
71
133
|
sweep() {
|
|
72
134
|
for (const [id, value] of this.entries()) {
|
|
73
135
|
if (value.expired)
|
|
@@ -81,6 +143,9 @@ var _RateLimitManager = class extends Map {
|
|
|
81
143
|
};
|
|
82
144
|
var RateLimitManager = _RateLimitManager;
|
|
83
145
|
__name(RateLimitManager, "RateLimitManager");
|
|
146
|
+
/**
|
|
147
|
+
* The delay in milliseconds for {@link RateLimitManager.sweepInterval}.
|
|
148
|
+
*/
|
|
84
149
|
__publicField(RateLimitManager, "sweepIntervalDuration", 3e4);
|
|
85
150
|
|
|
86
151
|
export { RateLimit, RateLimitManager };
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/RateLimit.ts","../src/lib/RateLimitManager.ts"],"names":[],"mappings":";;;;;;;;;AAEO,IAAM,YAAN,MAA4B;AAAA,EAmB3B,YAAY,SAA8B;AAfjD,wBAAO;AAKP,wBAAO;AAKP,wBAAQ;AAMP,SAAK,UAAU;AACf,SAAK,MAAM;AAAA,EACZ;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,kBAAkB;AAAA,EAC/B;AAAA,EAKA,IAAW,UAAmB;AAC7B,WAAO,KAAK,cAAc,KAAK,CAAC,KAAK;AAAA,EACtC;AAAA,EAKA,IAAW,gBAAwB;AAClC,WAAO,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAAG,CAAC;AAAA,EAC7C;AAAA,EAKO,UAAgB;AACtB,QAAI,KAAK;AAAS,YAAM,IAAI,MAAM,iCAAiC;AACnE,QAAI,KAAK;AAAS,WAAK,MAAM;AAE7B,SAAK;AACL,WAAO;AAAA,EACR;AAAA,EAKO,QAAc;AACpB,WAAO,KAAK,eAAe,EAAE,UAAU;AAAA,EACxC;AAAA,EAKO,iBAAuB;AAC7B,SAAK,YAAY,KAAK,QAAQ;AAC9B,WAAO;AAAA,EACR;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,EAoB/D,YAAY,MAAc,QAAQ,GAAG;AAC3C,UAAM;AAjBP,wBAAgB;AAKhB,wBAAgB;AAKhB,wBAAQ;AASP,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACd;AAAA,EAMO,QAAQ,IAAqB;AACnC,WAAO,KAAK,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE;AAAA,EACtC;AAAA,EAMO,OAAO,IAAqB;AAClC,UAAM,QAAQ,IAAI,UAAU,IAAI;AAChC,SAAK,IAAI,IAAI,KAAK;AAClB,WAAO;AAAA,EACR;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,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;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"]}
|
|
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.cf249ce.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.
|
|
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
66
|
"typedoc-json-parser": "^7.1.0",
|
|
67
|
-
"typescript": "^4.9.
|
|
68
|
-
"vitest": "^0.
|
|
67
|
+
"typescript": "^4.9.5",
|
|
68
|
+
"vitest": "^0.28.4"
|
|
69
69
|
}
|
|
70
70
|
}
|