tiny-essentials 1.8.5 → 1.9.1

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.
@@ -2145,6 +2145,7 @@ __webpack_require__.d(__webpack_exports__, {
2145
2145
  ColorSafeStringify: () => (/* reexport */ libs_ColorSafeStringify),
2146
2146
  TinyLevelUp: () => (/* reexport */ userLevel),
2147
2147
  TinyPromiseQueue: () => (/* reexport */ libs_TinyPromiseQueue),
2148
+ TinyRateLimiter: () => (/* reexport */ libs_TinyRateLimiter),
2148
2149
  addAiMarkerShortcut: () => (/* reexport */ addAiMarkerShortcut),
2149
2150
  arraySortPositions: () => (/* reexport */ arraySortPositions),
2150
2151
  asyncReplace: () => (/* reexport */ asyncReplace),
@@ -2201,6 +2202,15 @@ async function asyncReplace(str, regex, asyncFn) {
2201
2202
  }
2202
2203
 
2203
2204
  ;// ./src/legacy/libs/userLevel.mjs
2205
+ /**
2206
+ * Represents a user object used.
2207
+ *
2208
+ * @typedef {Object} UserEditor
2209
+ * @property {number} exp - Current experience points of the user.
2210
+ * @property {number} level - Current level of the user.
2211
+ * @property {number} totalExp - Total accumulated experience.
2212
+ */
2213
+
2204
2214
  /**
2205
2215
  * Class to manage user level-up logic based on experience points.
2206
2216
  */
@@ -2211,26 +2221,95 @@ class TinyLevelUp {
2211
2221
  * @param {number} expLevel - Base experience needed to level up (per level).
2212
2222
  */
2213
2223
  constructor(giveExp, expLevel) {
2224
+ if (typeof giveExp !== 'number' || Number.isNaN(giveExp))
2225
+ throw new Error('giveExp must be a valid number');
2226
+ if (typeof expLevel !== 'number' || Number.isNaN(expLevel))
2227
+ throw new Error('expLevel must be a valid number');
2214
2228
  this.giveExp = giveExp;
2215
2229
  this.expLevel = expLevel;
2216
2230
  }
2217
2231
 
2218
2232
  /**
2219
- * @typedef {{ exp: number, level: number, totalExp: number }} UserResult
2233
+ * Creates a new user object starting at level 0 with 0 experience.
2234
+ * @returns {UserEditor} A fresh user object.
2235
+ */
2236
+ createUser() {
2237
+ return {
2238
+ exp: 0,
2239
+ level: 1,
2240
+ totalExp: 0,
2241
+ };
2242
+ }
2243
+
2244
+ /**
2245
+ * Validates if the given user object has valid numeric properties.
2246
+ * Throws an error if any property is invalid.
2247
+ *
2248
+ * @param {UserEditor} user - The user object to validate.
2249
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2250
+ */
2251
+ validateUser(user) {
2252
+ if (typeof user.exp !== 'number' || Number.isNaN(user.exp))
2253
+ throw new Error('exp must be a valid number');
2254
+ if (typeof user.level !== 'number' || Number.isNaN(user.level))
2255
+ throw new Error('level must be a valid number');
2256
+ if (user.level < 1) throw new Error('level must be at least 1');
2257
+ if (typeof user.totalExp !== 'number' || Number.isNaN(user.totalExp))
2258
+ throw new Error('totalExp must be a valid number');
2259
+ }
2260
+
2261
+ /**
2262
+ * Checks if the given user object is valid by verifying its numeric properties.
2263
+ *
2264
+ * @param {UserEditor} user - The user object to check.
2265
+ * @returns {boolean} `true` if all properties (exp, level, totalExp) are valid numbers; otherwise `false`.
2220
2266
  */
2267
+ isValidUser(user) {
2268
+ if (typeof user.exp !== 'number' || Number.isNaN(user.exp)) return false;
2269
+ if (typeof user.level !== 'number' || Number.isNaN(user.level)) return false;
2270
+ if (user.level < 1) return false;
2271
+ if (typeof user.totalExp !== 'number' || Number.isNaN(user.totalExp)) return false;
2272
+ return true;
2273
+ }
2274
+
2275
+ /**
2276
+ * Returns the base experience value used for random experience generation.
2277
+ * Throws an error if the internal giveExp value is not a valid number.
2278
+ *
2279
+ * @returns {number} The base experience value.
2280
+ * @throws {Error} If giveExp is not a valid number.
2281
+ */
2282
+ getGiveExpBase() {
2283
+ if (typeof this.giveExp !== 'number' || Number.isNaN(this.giveExp))
2284
+ throw new Error('giveExp must be a valid number');
2285
+ return this.giveExp;
2286
+ }
2221
2287
 
2222
2288
  /**
2223
- * @typedef {{ exp: number, level: number, totalExp: any }} UserEditor
2289
+ * Returns the base experience required to level up.
2290
+ * Throws an error if the internal expLevel value is not a valid number.
2291
+ *
2292
+ * @returns {number} The base experience needed per level.
2293
+ * @throws {Error} If expLevel is not a valid number.
2224
2294
  */
2295
+ getExpLevelBase() {
2296
+ if (typeof this.expLevel !== 'number' || Number.isNaN(this.expLevel))
2297
+ throw new Error('expLevel must be a valid number');
2298
+ return this.expLevel;
2299
+ }
2225
2300
 
2226
2301
  /**
2227
2302
  * Validates and adjusts the user's level based on their current experience.
2228
2303
  * @param {UserEditor} user - The user object containing experience and level properties.
2229
- * @returns {UserResult} The updated user object.
2304
+ * @returns {UserEditor} The updated user object.
2305
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2230
2306
  */
2231
2307
  expValidator(user) {
2308
+ const expLevel = this.getExpLevelBase();
2309
+ this.validateUser(user);
2310
+
2232
2311
  let extraValue = 0;
2233
- const nextLevelExp = this.expLevel * user.level;
2312
+ const nextLevelExp = expLevel * user.level;
2234
2313
 
2235
2314
  // Level Up
2236
2315
  if (user.exp >= nextLevelExp) {
@@ -2245,7 +2324,7 @@ class TinyLevelUp {
2245
2324
  if (user.exp < 1 && user.level > 1) {
2246
2325
  user.level--;
2247
2326
  extraValue = Math.abs(user.exp);
2248
- user.exp = this.expLevel * user.level;
2327
+ user.exp = expLevel * user.level;
2249
2328
 
2250
2329
  if (extraValue > 0) return this.remove(user, extraValue, 'extra');
2251
2330
  }
@@ -2255,12 +2334,14 @@ class TinyLevelUp {
2255
2334
 
2256
2335
  /**
2257
2336
  * Calculates the total experience based on the user's level.
2258
- * @param {{ exp: number, level: number }} user - The user object containing experience and level properties.
2337
+ * @param {UserEditor} user - The user object containing experience and level properties.
2259
2338
  * @returns {number} The total experience of the user.
2339
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2260
2340
  */
2261
2341
  getTotalExp(user) {
2342
+ this.validateUser(user);
2262
2343
  let totalExp = 0;
2263
- for (let p = 1; p <= user.level; p++) totalExp += this.expLevel * p;
2344
+ for (let p = 1; p <= user.level; p++) totalExp += this.getExpLevelBase() * p;
2264
2345
  totalExp += user.exp;
2265
2346
  return totalExp;
2266
2347
  }
@@ -2271,34 +2352,52 @@ class TinyLevelUp {
2271
2352
  * @returns {number} The generated experience points.
2272
2353
  */
2273
2354
  expGenerator(multi = 1) {
2274
- return Math.floor(Math.random() * this.giveExp) + 1 * multi;
2355
+ if (typeof multi !== 'number' || Number.isNaN(multi))
2356
+ throw new Error('multi must be a valid number');
2357
+ return Math.floor(Math.random() * this.getGiveExpBase()) * multi;
2358
+ }
2359
+
2360
+ /**
2361
+ * Calculates how much experience is missing to next level.
2362
+ * @param {UserEditor} user
2363
+ * @returns {number}
2364
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2365
+ */
2366
+ getMissingExp(user) {
2367
+ return this.getProgress(user) - user.exp;
2275
2368
  }
2276
2369
 
2277
2370
  /**
2278
2371
  * Gets the experience points required to reach the next level.
2279
- * @param {{ level: number }} user - The user object containing the level.
2372
+ * @param {UserEditor} user - The user object containing the level.
2280
2373
  * @returns {number} The experience required for the next level.
2374
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2281
2375
  */
2282
2376
  progress(user) {
2283
- return this.expLevel * user.level;
2377
+ return this.getProgress(user);
2284
2378
  }
2285
2379
 
2286
2380
  /**
2287
2381
  * Gets the experience points required to reach the next level.
2288
- * @param {{ level: number }} user - The user object containing the level.
2382
+ * @param {UserEditor} user - The user object containing the level.
2289
2383
  * @returns {number} The experience required for the next level.
2384
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2290
2385
  */
2291
2386
  getProgress(user) {
2292
- return this.expLevel * user.level;
2387
+ this.validateUser(user);
2388
+ return this.getExpLevelBase() * user.level;
2293
2389
  }
2294
2390
 
2295
2391
  /**
2296
2392
  * Sets the experience value for the user, adjusting their level if necessary.
2297
2393
  * @param {UserEditor} user - The user object.
2298
2394
  * @param {number} value - The new experience value to set.
2299
- * @returns {UserResult} The updated user object.
2395
+ * @returns {UserEditor} The updated user object.
2300
2396
  */
2301
2397
  set(user, value) {
2398
+ if (typeof value !== 'number' || Number.isNaN(value))
2399
+ throw new Error('value must be a valid number');
2400
+
2302
2401
  user.exp = value;
2303
2402
  this.expValidator(user);
2304
2403
  user.totalExp = this.getTotalExp(user);
@@ -2311,9 +2410,15 @@ class TinyLevelUp {
2311
2410
  * @param {number} [extraExp] - Additional experience to be added.
2312
2411
  * @param {'add' | 'extra'} [type] - Type of addition ('add' or 'extra').
2313
2412
  * @param {number} [multi] - Multiplier for experience generation.
2314
- * @returns {UserResult} The updated user object.
2413
+ * @returns {UserEditor} The updated user object.
2315
2414
  */
2316
2415
  give(user, extraExp = 0, type = 'add', multi = 1) {
2416
+ if (typeof multi !== 'number' || Number.isNaN(multi))
2417
+ throw new Error('multi must be a valid number');
2418
+ if (typeof extraExp !== 'number' || Number.isNaN(extraExp))
2419
+ throw new Error('extraExp must be a valid number');
2420
+ if (typeof type !== 'string') throw new Error('type must be a valid string');
2421
+
2317
2422
  if (type === 'add') user.exp += this.expGenerator(multi) + extraExp;
2318
2423
  else if (type === 'extra') user.exp += extraExp;
2319
2424
 
@@ -2328,9 +2433,15 @@ class TinyLevelUp {
2328
2433
  * @param {number} [extraExp] - Additional experience to remove.
2329
2434
  * @param {'add' | 'extra'} [type] - Type of removal ('add' or 'extra').
2330
2435
  * @param {number} [multi] - Multiplier for experience generation.
2331
- * @returns {UserResult} The updated user object.
2436
+ * @returns {UserEditor} The updated user object.
2332
2437
  */
2333
2438
  remove(user, extraExp = 0, type = 'add', multi = 1) {
2439
+ if (typeof multi !== 'number' || Number.isNaN(multi))
2440
+ throw new Error('multi must be a valid number');
2441
+ if (typeof extraExp !== 'number' || Number.isNaN(extraExp))
2442
+ throw new Error('extraExp must be a valid number');
2443
+ if (typeof type !== 'string') throw new Error('type must be a valid string');
2444
+
2334
2445
  if (type === 'add') user.exp -= this.expGenerator(multi) + extraExp;
2335
2446
  else if (type === 'extra') user.exp -= extraExp;
2336
2447
 
@@ -3310,6 +3421,16 @@ class ColorSafeStringify {
3310
3421
  /* harmony default export */ const libs_ColorSafeStringify = (ColorSafeStringify);
3311
3422
 
3312
3423
  ;// ./src/v1/libs/TinyPromiseQueue.mjs
3424
+ /**
3425
+ * @typedef {Object} QueuedTask
3426
+ * @property {(...args: any[]) => Promise<any>|Promise<any>} task - The async task to execute.
3427
+ * @property {(value: any) => any} resolve - The resolve function from the Promise.
3428
+ * @property {(reason?: any) => any} reject - The reject function from the Promise.
3429
+ * @property {string|undefined} [id] - Optional identifier for the task.
3430
+ * @property {string|null|undefined} [marker] - Optional marker for the task.
3431
+ * @property {number|null|undefined} [delay] - Optional delay (in ms) before the task is executed.
3432
+ */
3433
+
3313
3434
  /**
3314
3435
  * A queue system for managing and executing asynchronous tasks sequentially, one at a time.
3315
3436
  *
@@ -3319,20 +3440,10 @@ class ColorSafeStringify {
3319
3440
  * @class
3320
3441
  */
3321
3442
  class TinyPromiseQueue {
3322
- /**
3323
- * @typedef {Object} QueuedTask
3324
- * @property {(...args: any[]) => Promise<any>|Promise<any>} task - The async task to execute.
3325
- * @property {(value: any) => any} resolve - The resolve function from the Promise.
3326
- * @property {(reason?: any) => any} reject - The reject function from the Promise.
3327
- * @property {string|undefined} [id] - Optional identifier for the task.
3328
- * @property {string|null|undefined} [marker] - Optional marker for the task.
3329
- * @property {number|null|undefined} [delay] - Optional delay (in ms) before the task is executed.
3330
- */
3331
-
3332
- /** @type {Array<QueuedTask>} */
3443
+ /** @type {QueuedTask[]} */
3333
3444
  #queue = [];
3334
3445
  #running = false;
3335
- /** @type {Record<string, *>} */
3446
+ /** @type {Record<string, ReturnType<typeof setTimeout>>} */
3336
3447
  #timeouts = {};
3337
3448
  /** @type {Set<string>} */
3338
3449
  #blacklist = new Set();
@@ -3495,8 +3606,13 @@ class TinyPromiseQueue {
3495
3606
  * @param {(...args: any[]) => Promise<any>|Promise<any>} task A function that returns a Promise.
3496
3607
  * @param {string} [id] Optional ID to identify the task in the queue.
3497
3608
  * @returns {Promise<any>} A Promise that resolves or rejects with the result of the task once it's processed.
3609
+ * @throws {Error} Throws if param is invalid.
3498
3610
  */
3499
3611
  async enqueuePoint(task, id) {
3612
+ if (typeof task !== 'function')
3613
+ return Promise.reject(new Error('Task must be a function returning a Promise.'));
3614
+ if (typeof id !== 'undefined' && typeof id !== 'string')
3615
+ throw new Error('The "id" parameter must be a string.');
3500
3616
  if (!this.#running) return task();
3501
3617
  return new Promise((resolve, reject) => {
3502
3618
  this.#queue.push({ marker: 'POINT_MARKER', task, resolve, reject, id });
@@ -3515,8 +3631,16 @@ class TinyPromiseQueue {
3515
3631
  * @param {number|null} [delay] Optional delay (in ms) before the task is executed.
3516
3632
  * @param {string} [id] Optional ID to identify the task in the queue.
3517
3633
  * @returns {Promise<any>} A Promise that resolves or rejects with the result of the task once it's processed.
3634
+ * @throws {Error} Throws if param is invalid.
3518
3635
  */
3519
3636
  enqueue(task, delay, id) {
3637
+ if (typeof task !== 'function')
3638
+ return Promise.reject(new Error('Task must be a function returning a Promise.'));
3639
+ if (typeof delay !== 'undefined' && (typeof delay !== 'number' || delay < 0))
3640
+ return Promise.reject(new Error('Delay must be a positive number or undefined.'));
3641
+ if (typeof id !== 'undefined' && typeof id !== 'string')
3642
+ throw new Error('The "id" parameter must be a string.');
3643
+
3520
3644
  return new Promise((resolve, reject) => {
3521
3645
  this.#queue.push({ task, resolve, reject, id, delay });
3522
3646
  this.#processQueue();
@@ -3529,9 +3653,10 @@ class TinyPromiseQueue {
3529
3653
  *
3530
3654
  * @param {string} id The ID of the task to cancel.
3531
3655
  * @returns {boolean} True if a delay was cancelled and the task was removed.
3656
+ * @throws {Error} Throws if `id` is not a string.
3532
3657
  */
3533
3658
  cancelTask(id) {
3534
- if (!id) return false;
3659
+ if (typeof id !== 'string') throw new Error('The "id" parameter must be a string.');
3535
3660
  let cancelled = false;
3536
3661
 
3537
3662
  if (id in this.#timeouts) {
@@ -3555,6 +3680,203 @@ class TinyPromiseQueue {
3555
3680
 
3556
3681
  /* harmony default export */ const libs_TinyPromiseQueue = (TinyPromiseQueue);
3557
3682
 
3683
+ ;// ./src/v1/libs/TinyRateLimiter.mjs
3684
+ /**
3685
+ * Class representing a flexible rate limiter per user.
3686
+ *
3687
+ * This rate limiter can be configured by maximum number of hits,
3688
+ * time interval, or a combination of both. It supports automatic
3689
+ * cleanup of inactive users to optimize memory usage.
3690
+ *
3691
+ * @class
3692
+ */
3693
+ class TinyRateLimiter {
3694
+ /**
3695
+ * @param {Object} options
3696
+ * @param {number} [options.maxHits] - Max interactions allowed
3697
+ * @param {number} [options.interval] - Time window in milliseconds
3698
+ * @param {number} [options.cleanupInterval] - Interval for automatic cleanup (ms)
3699
+ * @param {number} [options.maxIdle=300000] - Max idle time for a user before being cleaned (ms)
3700
+ */
3701
+ constructor({ maxHits, interval, cleanupInterval, maxIdle = 300000 }) {
3702
+ /** @param {number|undefined} val */
3703
+ const isPositiveInteger = (val) =>
3704
+ typeof val === 'number' && Number.isFinite(val) && val >= 1 && Number.isInteger(val);
3705
+
3706
+ const isMaxHitsValid = isPositiveInteger(maxHits);
3707
+ const isIntervalValid = isPositiveInteger(interval);
3708
+ const isCleanupValid = isPositiveInteger(cleanupInterval);
3709
+ const isMaxIdleValid = isPositiveInteger(maxIdle);
3710
+
3711
+ if (!isMaxHitsValid && !isIntervalValid)
3712
+ throw new Error("RateLimiter requires at least one valid option: 'maxHits' or 'interval'.");
3713
+ if (maxHits !== undefined && !isMaxHitsValid)
3714
+ throw new Error("'maxHits' must be a positive integer if defined.");
3715
+ if (interval !== undefined && !isIntervalValid)
3716
+ throw new Error("'interval' must be a positive integer in milliseconds if defined.");
3717
+ if (cleanupInterval !== undefined && !isCleanupValid)
3718
+ throw new Error("'cleanupInterval' must be a positive integer in milliseconds if defined.");
3719
+ if (!isMaxIdleValid) throw new Error("'maxIdle' must be a positive integer in milliseconds.");
3720
+
3721
+ this.maxHits = isMaxHitsValid ? maxHits : null;
3722
+ this.interval = isIntervalValid ? interval : null;
3723
+ this.cleanupInterval = isCleanupValid ? cleanupInterval : null;
3724
+ this.maxIdle = maxIdle;
3725
+
3726
+ /** @type {Map<string, number[]>} */
3727
+ this.userData = new Map();
3728
+
3729
+ /** @type {Map<string, number>} */
3730
+ this.lastSeen = new Map();
3731
+
3732
+ // Start automatic cleanup only if cleanupInterval is valid
3733
+ if (this.cleanupInterval !== null)
3734
+ this._cleanupTimer = setInterval(() => this._cleanup(), this.cleanupInterval);
3735
+ }
3736
+
3737
+ /**
3738
+ * Get the interval window in milliseconds.
3739
+ *
3740
+ * @returns {number} The interval value.
3741
+ * @throws {Error} If interval is not a valid finite number.
3742
+ */
3743
+ getInterval() {
3744
+ if (typeof this.interval !== 'number' || !Number.isFinite(this.interval))
3745
+ throw new Error("'interval' is not a valid finite number.");
3746
+ return this.interval;
3747
+ }
3748
+
3749
+ /**
3750
+ * Get the maximum number of allowed hits.
3751
+ *
3752
+ * @returns {number} The maxHits value.
3753
+ * @throws {Error} If maxHits is not a valid finite number.
3754
+ */
3755
+ getMaxHits() {
3756
+ if (typeof this.maxHits !== 'number' || !Number.isFinite(this.maxHits)) {
3757
+ throw new Error("'maxHits' is not a valid finite number.");
3758
+ }
3759
+ return this.maxHits;
3760
+ }
3761
+
3762
+ /**
3763
+ * Register a hit for a specific user
3764
+ * @param {string} userId
3765
+ */
3766
+ hit(userId) {
3767
+ const now = Date.now();
3768
+
3769
+ if (!this.userData.has(userId)) {
3770
+ this.userData.set(userId, []);
3771
+ }
3772
+
3773
+ const history = this.userData.get(userId);
3774
+ if (!history) throw new Error(`No data found for userId: ${userId}`);
3775
+
3776
+ history.push(now);
3777
+ this.lastSeen.set(userId, now);
3778
+
3779
+ // Clean up old entries
3780
+ if (this.interval !== null) {
3781
+ const interval = this.getInterval();
3782
+ const cutoff = now - interval;
3783
+ while (history.length && history[0] < cutoff) {
3784
+ history.shift();
3785
+ }
3786
+ }
3787
+
3788
+ // Optional: keep only the last N entries for memory optimization
3789
+ if (this.maxHits !== null) {
3790
+ const maxHits = this.getMaxHits();
3791
+ if (history.length > maxHits) {
3792
+ history.splice(0, history.length - maxHits);
3793
+ }
3794
+ }
3795
+ }
3796
+
3797
+ /**
3798
+ * Check if the user is currently rate limited
3799
+ * @param {string} userId
3800
+ * @returns {boolean}
3801
+ */
3802
+ isRateLimited(userId) {
3803
+ const now = Date.now();
3804
+
3805
+ if (!this.userData.has(userId)) return false;
3806
+
3807
+ const history = this.userData.get(userId);
3808
+ if (!history) throw new Error(`No data found for userId: ${userId}`);
3809
+
3810
+ if (this.interval !== null) {
3811
+ const interval = this.getInterval();
3812
+ const recent = history.filter((t) => t > now - interval);
3813
+ if (this.maxHits !== null) {
3814
+ return recent.length >= this.getMaxHits();
3815
+ }
3816
+ return recent.length > 0;
3817
+ }
3818
+
3819
+ if (this.maxHits !== null) {
3820
+ return history.length >= this.getMaxHits();
3821
+ }
3822
+
3823
+ return false;
3824
+ }
3825
+
3826
+ /**
3827
+ * Manually reset user data
3828
+ * @param {string} userId
3829
+ */
3830
+ reset(userId) {
3831
+ this.userData.delete(userId);
3832
+ this.lastSeen.delete(userId);
3833
+ }
3834
+
3835
+ /**
3836
+ * Set hit timestamps for a user
3837
+ * @param {string} userId
3838
+ * @param {number[]} timestamps
3839
+ */
3840
+ setData(userId, timestamps) {
3841
+ this.userData.set(userId, timestamps);
3842
+ this.lastSeen.set(userId, Date.now());
3843
+ }
3844
+
3845
+ /**
3846
+ * Get timestamps from user
3847
+ * @param {string} userId
3848
+ * @returns {number[]}
3849
+ */
3850
+ getData(userId) {
3851
+ return this.userData.get(userId) || [];
3852
+ }
3853
+
3854
+ /**
3855
+ * Cleanup old/inactive users
3856
+ * @private
3857
+ */
3858
+ _cleanup() {
3859
+ const now = Date.now();
3860
+ for (const [userId, last] of this.lastSeen.entries()) {
3861
+ if (now - last > this.maxIdle) {
3862
+ this.userData.delete(userId);
3863
+ this.lastSeen.delete(userId);
3864
+ }
3865
+ }
3866
+ }
3867
+
3868
+ /**
3869
+ * Destroy the rate limiter, stopping all intervals
3870
+ */
3871
+ destroy() {
3872
+ if (this._cleanupTimer) clearInterval(this._cleanupTimer);
3873
+ this.userData.clear();
3874
+ this.lastSeen.clear();
3875
+ }
3876
+ }
3877
+
3878
+ /* harmony default export */ const libs_TinyRateLimiter = (TinyRateLimiter);
3879
+
3558
3880
  ;// ./src/v1/index.mjs
3559
3881
 
3560
3882
 
@@ -3569,6 +3891,7 @@ class TinyPromiseQueue {
3569
3891
 
3570
3892
 
3571
3893
 
3894
+
3572
3895
  })();
3573
3896
 
3574
3897
  window.TinyEssentials = __webpack_exports__;