tiny-essentials 1.19.3 → 1.20.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.
Files changed (57) hide show
  1. package/dist/v1/TinyBasicsEs.min.js +1 -1
  2. package/dist/v1/TinyDragger.min.js +1 -1
  3. package/dist/v1/TinyEssentials.min.js +1 -1
  4. package/dist/v1/TinyHtml.min.js +1 -1
  5. package/dist/v1/TinyIframeEvents.min.js +1 -0
  6. package/dist/v1/TinyNewWinEvents.min.js +1 -0
  7. package/dist/v1/TinySmartScroller.min.js +1 -1
  8. package/dist/v1/TinyUploadClicker.min.js +1 -1
  9. package/dist/v1/build/TinyIframeEvents.cjs +7 -0
  10. package/dist/v1/build/TinyIframeEvents.d.mts +3 -0
  11. package/dist/v1/build/TinyIframeEvents.mjs +2 -0
  12. package/dist/v1/build/TinyNewWinEvents.cjs +7 -0
  13. package/dist/v1/build/TinyNewWinEvents.d.mts +3 -0
  14. package/dist/v1/build/TinyNewWinEvents.mjs +2 -0
  15. package/dist/v1/index.cjs +4 -0
  16. package/dist/v1/index.d.mts +3 -1
  17. package/dist/v1/index.mjs +3 -1
  18. package/dist/v1/libs/TinyDragger.cjs +1 -1
  19. package/dist/v1/libs/TinyDragger.mjs +1 -1
  20. package/dist/v1/libs/TinyHtml.cjs +292 -103
  21. package/dist/v1/libs/TinyHtml.d.mts +142 -39
  22. package/dist/v1/libs/TinyHtml.mjs +266 -94
  23. package/dist/v1/libs/TinyIframeEvents.cjs +410 -0
  24. package/dist/v1/libs/TinyIframeEvents.d.mts +193 -0
  25. package/dist/v1/libs/TinyIframeEvents.mjs +348 -0
  26. package/dist/v1/libs/TinyNewWinEvents.cjs +488 -0
  27. package/dist/v1/libs/TinyNewWinEvents.d.mts +241 -0
  28. package/dist/v1/libs/TinyNewWinEvents.mjs +437 -0
  29. package/docs/v1/README.md +2 -0
  30. package/docs/v1/libs/TinyHtml.md +128 -6
  31. package/docs/v1/libs/TinyIframeEvents.md +149 -0
  32. package/docs/v1/libs/TinyNewWinEvents.md +186 -0
  33. package/docs/v1/libs/TinyNotifyCenter.md +1 -1
  34. package/package.json +1 -1
  35. package/dist/v1/ColorSafeStringify.js +0 -235
  36. package/dist/v1/TinyAfterScrollWatcher.js +0 -219
  37. package/dist/v1/TinyBasicsEs.js +0 -9334
  38. package/dist/v1/TinyClipboard.js +0 -459
  39. package/dist/v1/TinyColorConverter.js +0 -617
  40. package/dist/v1/TinyDomReadyManager.js +0 -213
  41. package/dist/v1/TinyDragDropDetector.js +0 -307
  42. package/dist/v1/TinyDragger.js +0 -6569
  43. package/dist/v1/TinyEssentials.js +0 -19893
  44. package/dist/v1/TinyEvents.js +0 -402
  45. package/dist/v1/TinyHtml.js +0 -5545
  46. package/dist/v1/TinyLevelUp.js +0 -291
  47. package/dist/v1/TinyLocalStorage.js +0 -1440
  48. package/dist/v1/TinyNotifications.js +0 -408
  49. package/dist/v1/TinyNotifyCenter.js +0 -493
  50. package/dist/v1/TinyPromiseQueue.js +0 -299
  51. package/dist/v1/TinyRateLimiter.js +0 -611
  52. package/dist/v1/TinySmartScroller.js +0 -7039
  53. package/dist/v1/TinyTextRangeEditor.js +0 -497
  54. package/dist/v1/TinyTimeout.js +0 -233
  55. package/dist/v1/TinyToastNotify.js +0 -441
  56. package/dist/v1/TinyUploadClicker.js +0 -13456
  57. package/dist/v1/UltraRandomMsgGen.js +0 -995
@@ -1,611 +0,0 @@
1
- /******/ (() => { // webpackBootstrap
2
- /******/ "use strict";
3
- /******/ // The require scope
4
- /******/ var __webpack_require__ = {};
5
- /******/
6
- /************************************************************************/
7
- /******/ /* webpack/runtime/define property getters */
8
- /******/ (() => {
9
- /******/ // define getter functions for harmony exports
10
- /******/ __webpack_require__.d = (exports, definition) => {
11
- /******/ for(var key in definition) {
12
- /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
13
- /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
14
- /******/ }
15
- /******/ }
16
- /******/ };
17
- /******/ })();
18
- /******/
19
- /******/ /* webpack/runtime/hasOwnProperty shorthand */
20
- /******/ (() => {
21
- /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
22
- /******/ })();
23
- /******/
24
- /************************************************************************/
25
- var __webpack_exports__ = {};
26
-
27
- // EXPORTS
28
- __webpack_require__.d(__webpack_exports__, {
29
- TinyRateLimiter: () => (/* reexport */ libs_TinyRateLimiter)
30
- });
31
-
32
- ;// ./src/v1/libs/TinyRateLimiter.mjs
33
- /** @typedef {(groupId: string) => void} OnMemoryExceeded */
34
-
35
- /** @typedef {(groupId: string) => void} OnGroupExpired */
36
-
37
- /**
38
- * Class representing a flexible rate limiter per user or group.
39
- *
40
- * This rate limiter supports limiting per user or per group by mapping
41
- * userIds to a common groupId. All users within the same group share
42
- * rate limits.
43
- */
44
- class TinyRateLimiter {
45
- /** @type {number|null} */
46
- #maxMemory = null;
47
-
48
- /** @type {NodeJS.Timeout|null} */
49
- #cleanupTimer = null;
50
-
51
- /** @type {number|null|undefined} */
52
- #maxHits = null;
53
-
54
- /** @type {number|null|undefined} */
55
- #interval = null;
56
-
57
- /** @type {number|null|undefined} */
58
- #cleanupInterval = null;
59
-
60
- /** @type {number|null|undefined} */
61
- #maxIdle = null;
62
-
63
- /** @type {Map<string, number[]>} */
64
- groupData = new Map(); // groupId -> timestamps[]
65
-
66
- /** @type {Map<string, number>} */
67
- lastSeen = new Map(); // groupId -> timestamp
68
-
69
- /** @type {Map<string, string>} */
70
- userToGroup = new Map(); // userId -> groupId
71
-
72
- /** @type {Map<string, boolean>} */
73
- groupFlags = new Map(); // groupId -> boolean
74
-
75
- /**
76
- * @type {Map<string, number>}
77
- * Stores TTL (in ms) for each groupId individually
78
- */
79
- groupTTL = new Map();
80
-
81
- /**
82
- * @type {null|OnMemoryExceeded}
83
- */
84
- #onMemoryExceeded = null;
85
-
86
- /**
87
- * Set the callback to be triggered when a group exceeds its limit
88
- * @param {OnMemoryExceeded} callback
89
- */
90
- setOnMemoryExceeded(callback) {
91
- if (typeof callback !== 'function') throw new Error('onMemoryExceeded must be a function');
92
- this.#onMemoryExceeded = callback;
93
- }
94
-
95
- /**
96
- * Clear the onMemoryExceeded callback
97
- */
98
- clearOnMemoryExceeded() {
99
- this.#onMemoryExceeded = null;
100
- }
101
-
102
- /**
103
- * @type {null|OnGroupExpired}
104
- */
105
- #onGroupExpired = null;
106
-
107
- /**
108
- * Set the callback to be triggered when a group expires and is removed.
109
- *
110
- * This callback is called automatically during cleanup when a group
111
- * becomes inactive for longer than its TTL.
112
- *
113
- * @param {OnGroupExpired} callback - A function that receives the expired groupId.
114
- */
115
- setOnGroupExpired(callback) {
116
- if (typeof callback !== 'function') throw new Error('onGroupExpired must be a function');
117
- this.#onGroupExpired = callback;
118
- }
119
-
120
- /**
121
- * Clear the onGroupExpired callback
122
- */
123
- clearOnGroupExpired() {
124
- this.#onGroupExpired = null;
125
- }
126
-
127
- /**
128
- * @param {Object} options
129
- * @param {number|null} [options.maxMemory] - Max memory allowed
130
- * @param {number} [options.maxHits] - Max interactions allowed
131
- * @param {number} [options.interval] - Time window in milliseconds
132
- * @param {number} [options.cleanupInterval] - Interval for automatic cleanup (ms)
133
- * @param {number} [options.maxIdle=300000] - Max idle time for a user before being cleaned (ms)
134
- */
135
- constructor({ maxHits, interval, cleanupInterval, maxIdle = 300000, maxMemory = 100000 }) {
136
- /** @param {number|undefined} val */
137
- const isPositiveInteger = (val) =>
138
- typeof val === 'number' && Number.isFinite(val) && val >= 1 && Number.isInteger(val);
139
-
140
- const isMaxHitsValid = isPositiveInteger(maxHits);
141
- const isIntervalValid = isPositiveInteger(interval);
142
- const isCleanupValid = isPositiveInteger(cleanupInterval);
143
- const isMaxIdleValid = isPositiveInteger(maxIdle);
144
-
145
- if (!isMaxHitsValid && !isIntervalValid)
146
- throw new Error("RateLimiter requires at least one valid option: 'maxHits' or 'interval'.");
147
- if (maxHits !== undefined && !isMaxHitsValid)
148
- throw new Error("'maxHits' must be a positive integer if defined.");
149
- if (interval !== undefined && !isIntervalValid)
150
- throw new Error("'interval' must be a positive integer in milliseconds if defined.");
151
- if (cleanupInterval !== undefined && !isCleanupValid)
152
- throw new Error("'cleanupInterval' must be a positive integer in milliseconds if defined.");
153
- if (!isMaxIdleValid) throw new Error("'maxIdle' must be a positive integer in milliseconds.");
154
-
155
- if (typeof maxMemory === 'number' && Number.isFinite(maxMemory) && maxMemory > 0) {
156
- this.#maxMemory = Math.floor(maxMemory);
157
- } else if (maxMemory === null || maxMemory === undefined) {
158
- this.#maxMemory = null;
159
- } else {
160
- throw new Error('maxMemory must be a positive number or null');
161
- }
162
-
163
- this.#maxHits = isMaxHitsValid ? maxHits : null;
164
- this.#interval = isIntervalValid ? interval : null;
165
- this.#cleanupInterval = isCleanupValid ? cleanupInterval : null;
166
- this.#maxIdle = maxIdle;
167
-
168
- // Start automatic cleanup only if cleanupInterval is valid
169
- if (this.#cleanupInterval !== null)
170
- this.#cleanupTimer = setInterval(() => this._cleanup(), this.#cleanupInterval);
171
- }
172
-
173
- /**
174
- * Check if a given ID is a groupId (not a userId)
175
- * @param {string} id
176
- * @returns {boolean}
177
- */
178
- isGroupId(id) {
179
- const result = this.groupFlags.get(id);
180
- return typeof result === 'boolean' ? result : false;
181
- }
182
-
183
- /**
184
- * Get all user IDs that belong to a given group.
185
- * @param {string} groupId
186
- * @returns {string[]}
187
- */
188
- getUsersInGroup(groupId) {
189
- const users = [];
190
- for (const [userId, assignedGroup] of this.userToGroup.entries()) {
191
- if (assignedGroup === groupId) {
192
- users.push(userId);
193
- }
194
- }
195
-
196
- return users;
197
- }
198
-
199
- /**
200
- * Set TTL (in milliseconds) for a specific group
201
- * @param {string} groupId
202
- * @param {number} ttl
203
- */
204
- setGroupTTL(groupId, ttl) {
205
- if (typeof ttl !== 'number' || !Number.isFinite(ttl) || ttl <= 0)
206
- throw new Error('TTL must be a positive number in milliseconds');
207
- this.groupTTL.set(groupId, ttl);
208
- }
209
-
210
- /**
211
- * Get TTL (in ms) for a specific group.
212
- * @param {string} groupId
213
- * @returns {number|null}
214
- */
215
- getGroupTTL(groupId) {
216
- return this.groupTTL.get(groupId) ?? null;
217
- }
218
-
219
- /**
220
- * Delete the TTL setting for a specific group
221
- * @param {string} groupId
222
- */
223
- deleteGroupTTL(groupId) {
224
- this.groupTTL.delete(groupId);
225
- }
226
-
227
- /**
228
- * Assign a userId to a groupId, with merge if user has existing data.
229
- * @param {string} userId
230
- * @param {string} groupId
231
- * @throws {Error} If userId is already assigned to a different group
232
- */
233
- assignToGroup(userId, groupId) {
234
- const existingGroup = this.userToGroup.get(userId);
235
- if (existingGroup && existingGroup !== groupId)
236
- throw new Error(`User ${userId} is already assigned to group ${existingGroup}`);
237
-
238
- // If the user is already in the group, nothing needs to be done
239
- if (existingGroup === groupId) return;
240
- const userData = this.groupData.get(userId);
241
-
242
- // Associates the user to the group
243
- if (this.isGroupId(userId)) {
244
- for (const [uid, gId] of this.userToGroup.entries())
245
- if (gId === userId) this.userToGroup.set(uid, groupId);
246
- this.userToGroup.delete(userId);
247
- } else this.userToGroup.set(userId, groupId);
248
-
249
- // If the user has no data, nothing needs to be done
250
- if (!userData) return;
251
-
252
- const groupData = this.groupData.get(groupId);
253
- if (groupData) {
254
- for (const item of userData) groupData.push(item);
255
- } else {
256
- const newData = [];
257
- for (const item of userData) newData.push(item);
258
- this.groupData.set(groupId, newData);
259
- }
260
-
261
- this.lastSeen.set(groupId, Date.now());
262
-
263
- // Removes individual data as they are now in the group
264
- this.groupFlags.delete(userId);
265
- this.groupData.delete(userId);
266
- this.lastSeen.delete(userId);
267
- this.groupTTL.delete(userId);
268
- this.groupFlags.set(groupId, true);
269
- }
270
-
271
- /**
272
- * Get the groupId for a given userId
273
- * @param {string} userId
274
- * @returns {string}
275
- */
276
- getGroupId(userId) {
277
- return this.userToGroup.get(userId) || userId; // fallback: use userId as own group
278
- }
279
-
280
- /**
281
- * Register a hit for a specific user
282
- * @param {string} userId
283
- */
284
- hit(userId) {
285
- const groupId = this.getGroupId(userId);
286
- const now = Date.now();
287
-
288
- if (!this.groupData.has(groupId)) {
289
- this.groupData.set(groupId, []);
290
- this.groupFlags.set(groupId, false);
291
- }
292
-
293
- const history = this.groupData.get(groupId);
294
- if (!history) throw new Error(`No data found for groupId: ${groupId}`);
295
-
296
- history.push(now);
297
- this.lastSeen.set(groupId, now);
298
-
299
- // Clean up old entries
300
- if (this.#interval !== null) {
301
- const interval = this.getInterval();
302
- const cutoff = now - interval;
303
- while (history.length && history[0] < cutoff) {
304
- history.shift();
305
- }
306
- }
307
-
308
- // Optional: keep only the last N entries for memory optimization
309
- if (this.#maxMemory !== null && typeof this.#maxMemory === 'number') {
310
- if (history.length > this.#maxMemory) {
311
- history.splice(0, history.length - this.#maxMemory);
312
- if (typeof this.#onMemoryExceeded === 'function') this.#onMemoryExceeded(groupId);
313
- }
314
- }
315
- }
316
-
317
- /**
318
- * Check if the user (via their group) is currently rate limited
319
- * @param {string} userId
320
- * @returns {boolean}
321
- */
322
- isRateLimited(userId) {
323
- const groupId = this.getGroupId(userId);
324
- if (!this.groupData.has(groupId)) return false;
325
-
326
- const history = this.groupData.get(groupId);
327
- if (!history) throw new Error(`No data found for groupId: ${groupId}`);
328
-
329
- if (this.#interval !== null) {
330
- const now = Date.now();
331
- const interval = this.getInterval();
332
- const cutoff = now - interval;
333
- let count = 0;
334
- for (let i = history.length - 1; i >= 0; i--) {
335
- if (history[i] > cutoff) count++;
336
- else break;
337
- }
338
- if (this.#maxHits !== null) return count > this.getMaxHits();
339
- return count > 0;
340
- }
341
-
342
- if (this.#maxHits !== null) {
343
- return history.length > this.getMaxHits();
344
- }
345
-
346
- return false;
347
- }
348
-
349
- /**
350
- * Manually reset group data
351
- * @param {string} groupId
352
- */
353
- resetGroup(groupId) {
354
- this.groupFlags.delete(groupId);
355
- this.groupData.delete(groupId);
356
- this.lastSeen.delete(groupId);
357
- this.groupTTL.delete(groupId);
358
- }
359
-
360
- /**
361
- * Manually reset user data.
362
- *
363
- * @deprecated Use `resetUserGroup(userId)` instead. This method will be removed in future versions.
364
- * @param {string} userId
365
- * @returns {void}
366
- */
367
- reset(userId) {
368
- if (false)
369
- // removed by dead control flow
370
- {}
371
- return this.resetUserGroup(userId);
372
- }
373
-
374
- /**
375
- * Manually reset a user mapping
376
- * @param {string} userId
377
- */
378
- resetUserGroup(userId) {
379
- this.userToGroup.delete(userId);
380
- }
381
-
382
- /**
383
- * Set custom timestamps to a group
384
- * @param {string} groupId
385
- * @param {number[]} timestamps
386
- */
387
- setData(groupId, timestamps) {
388
- if (!Array.isArray(timestamps)) throw new Error('timestamps must be an array of numbers.');
389
- for (const t of timestamps) {
390
- if (typeof t !== 'number' || !Number.isFinite(t)) {
391
- throw new Error('All timestamps must be finite numbers.');
392
- }
393
- }
394
- if (!this.groupData.has(groupId)) this.groupFlags.set(groupId, false);
395
- this.groupData.set(groupId, timestamps);
396
- this.lastSeen.set(groupId, Date.now());
397
- }
398
-
399
- /**
400
- * Check if a group has data
401
- * @param {string} groupId
402
- * @returns {boolean}
403
- */
404
- hasData(groupId) {
405
- return this.groupData.has(groupId);
406
- }
407
-
408
- /**
409
- * Get timestamps from a group
410
- * @param {string} groupId
411
- * @returns {number[]}
412
- */
413
- getData(groupId) {
414
- return this.groupData.get(groupId) || [];
415
- }
416
-
417
- /**
418
- * Get the maximum idle time (in milliseconds) before a group is considered expired.
419
- * @returns {number}
420
- */
421
- getMaxIdle() {
422
- if (typeof this.#maxIdle !== 'number' || !Number.isFinite(this.#maxIdle) || this.#maxIdle < 0) {
423
- throw new Error("'maxIdle' must be a non-negative finite number.");
424
- }
425
- return this.#maxIdle;
426
- }
427
-
428
- /**
429
- * Set the maximum idle time (in milliseconds) before a group is considered expired.
430
- * @param {number} ms
431
- */
432
- setMaxIdle(ms) {
433
- if (typeof ms !== 'number' || !Number.isFinite(ms) || ms < 0) {
434
- throw new Error("'maxIdle' must be a non-negative finite number.");
435
- }
436
- this.#maxIdle = ms;
437
- }
438
-
439
- /**
440
- * Cleanup old/inactive groups with individual TTLs
441
- * @private
442
- */
443
- _cleanup() {
444
- const now = Date.now();
445
- for (const [groupId, last] of this.lastSeen.entries()) {
446
- const ttl = this.getGroupTTL(groupId) ?? this.getMaxIdle();
447
- if (now - last > ttl) {
448
- this.groupFlags.delete(groupId);
449
- this.groupData.delete(groupId);
450
- this.lastSeen.delete(groupId);
451
- this.groupTTL.delete(groupId);
452
-
453
- // Notify subclass or external binding
454
- if (typeof this.#onGroupExpired === 'function') {
455
- this.#onGroupExpired(groupId);
456
- }
457
- }
458
- }
459
- }
460
-
461
- /**
462
- * Get list of active group IDs
463
- * @returns {string[]}
464
- */
465
- getActiveGroups() {
466
- return Array.from(this.groupData.keys());
467
- }
468
-
469
- /**
470
- * Get a shallow copy of all user-to-group mappings as a plain object
471
- * @returns {Record<string, string>}
472
- */
473
- getAllUserMappings() {
474
- return Object.fromEntries(this.userToGroup);
475
- }
476
-
477
- /**
478
- * Get the interval window in milliseconds.
479
- * @returns {number}
480
- */
481
- getInterval() {
482
- if (typeof this.#interval !== 'number' || !Number.isFinite(this.#interval)) {
483
- throw new Error("'interval' is not a valid finite number.");
484
- }
485
- return this.#interval;
486
- }
487
-
488
- /**
489
- * Get the maximum number of allowed hits.
490
- * @returns {number}
491
- */
492
- getMaxHits() {
493
- if (typeof this.#maxHits !== 'number' || !Number.isFinite(this.#maxHits)) {
494
- throw new Error("'maxHits' is not a valid finite number.");
495
- }
496
- return this.#maxHits;
497
- }
498
-
499
- /**
500
- * Get the total number of hits recorded for a group.
501
- * @param {string} groupId
502
- * @returns {number}
503
- */
504
- getTotalHits(groupId) {
505
- const history = this.groupData.get(groupId);
506
- return Array.isArray(history) ? history.length : 0;
507
- }
508
-
509
- /**
510
- * Get the timestamp of the last hit for a group.
511
- * @param {string} groupId
512
- * @returns {number|null}
513
- */
514
- getLastHit(groupId) {
515
- const history = this.groupData.get(groupId);
516
- return history?.length ? history[history.length - 1] : null;
517
- }
518
-
519
- /**
520
- * Get milliseconds since the last hit for a group.
521
- * @param {string} groupId
522
- * @returns {number|null}
523
- */
524
- getTimeSinceLastHit(groupId) {
525
- const last = this.getLastHit(groupId);
526
- return last !== null ? Date.now() - last : null;
527
- }
528
-
529
- /**
530
- * Internal utility to compute average spacing
531
- * @private
532
- * @param {number[]|undefined} history
533
- * @returns {number|null}
534
- */
535
- _calculateAverageSpacing(history) {
536
- if (!Array.isArray(history) || history.length < 2) return null;
537
- let total = 0;
538
- for (let i = 1; i < history.length; i++) {
539
- total += history[i] - history[i - 1];
540
- }
541
- return total / (history.length - 1);
542
- }
543
-
544
- /**
545
- * Get average time between hits for a group (ms).
546
- * @param {string} groupId
547
- * @returns {number|null}
548
- */
549
- getAverageHitSpacing(groupId) {
550
- return this._calculateAverageSpacing(this.groupData.get(groupId));
551
- }
552
-
553
- /**
554
- * Get metrics about a group's activity.
555
- * @param {string} groupId
556
- * @returns {{
557
- * totalHits: number,
558
- * lastHit: number|null,
559
- * timeSinceLastHit: number|null,
560
- * averageHitSpacing: number|null
561
- * }}
562
- */
563
- getMetrics(groupId) {
564
- const history = this.groupData.get(groupId);
565
-
566
- if (!Array.isArray(history) || history.length === 0) {
567
- return {
568
- totalHits: 0,
569
- lastHit: null,
570
- timeSinceLastHit: null,
571
- averageHitSpacing: null,
572
- };
573
- }
574
-
575
- const totalHits = history.length;
576
- const lastHit = history[totalHits - 1];
577
- const timeSinceLastHit = Date.now() - lastHit;
578
- const averageHitSpacing = this._calculateAverageSpacing(history);
579
-
580
- return {
581
- totalHits,
582
- lastHit,
583
- timeSinceLastHit,
584
- averageHitSpacing,
585
- };
586
- }
587
-
588
- /**
589
- * Destroy the rate limiter, stopping cleanup and clearing data
590
- */
591
- destroy() {
592
- if (this.#cleanupTimer) clearInterval(this.#cleanupTimer);
593
- this._cleanup();
594
- this.groupData.clear();
595
- this.lastSeen.clear();
596
- this.userToGroup.clear();
597
- this.groupTTL.clear();
598
- this.groupFlags.clear();
599
- }
600
- }
601
-
602
- /* harmony default export */ const libs_TinyRateLimiter = (TinyRateLimiter);
603
-
604
- ;// ./src/v1/build/TinyRateLimiter.mjs
605
-
606
-
607
-
608
-
609
- window.TinyRateLimiter = __webpack_exports__.TinyRateLimiter;
610
- /******/ })()
611
- ;