tiny-essentials 1.9.1 → 1.10.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.
@@ -1,86 +1,241 @@
1
1
  export default TinyRateLimiter;
2
+ export type OnMemoryExceeded = (groupId: string) => void;
3
+ export type OnGroupExpired = (groupId: string) => void;
4
+ /** @typedef {(groupId: string) => void} OnMemoryExceeded */
5
+ /** @typedef {(groupId: string) => void} OnGroupExpired */
2
6
  /**
3
- * Class representing a flexible rate limiter per user.
7
+ * Class representing a flexible rate limiter per user or group.
4
8
  *
5
- * This rate limiter can be configured by maximum number of hits,
6
- * time interval, or a combination of both. It supports automatic
7
- * cleanup of inactive users to optimize memory usage.
8
- *
9
- * @class
9
+ * This rate limiter supports limiting per user or per group by mapping
10
+ * userIds to a common groupId. All users within the same group share
11
+ * rate limits.
10
12
  */
11
13
  declare class TinyRateLimiter {
12
14
  /**
13
15
  * @param {Object} options
16
+ * @param {number|null} [options.maxMemory] - Max memory allowed
14
17
  * @param {number} [options.maxHits] - Max interactions allowed
15
18
  * @param {number} [options.interval] - Time window in milliseconds
16
19
  * @param {number} [options.cleanupInterval] - Interval for automatic cleanup (ms)
17
20
  * @param {number} [options.maxIdle=300000] - Max idle time for a user before being cleaned (ms)
18
21
  */
19
- constructor({ maxHits, interval, cleanupInterval, maxIdle }: {
22
+ constructor({ maxHits, interval, cleanupInterval, maxIdle, maxMemory }: {
23
+ maxMemory?: number | null | undefined;
20
24
  maxHits?: number | undefined;
21
25
  interval?: number | undefined;
22
26
  cleanupInterval?: number | undefined;
23
27
  maxIdle?: number | undefined;
24
28
  });
25
- maxHits: number | null | undefined;
26
- interval: number | null | undefined;
27
- cleanupInterval: number | null | undefined;
28
- maxIdle: number;
29
29
  /** @type {Map<string, number[]>} */
30
- userData: Map<string, number[]>;
30
+ groupData: Map<string, number[]>;
31
31
  /** @type {Map<string, number>} */
32
32
  lastSeen: Map<string, number>;
33
- _cleanupTimer: NodeJS.Timeout | undefined;
33
+ /** @type {Map<string, string>} */
34
+ userToGroup: Map<string, string>;
35
+ /** @type {Map<string, boolean>} */
36
+ groupFlags: Map<string, boolean>;
34
37
  /**
35
- * Get the interval window in milliseconds.
36
- *
37
- * @returns {number} The interval value.
38
- * @throws {Error} If interval is not a valid finite number.
38
+ * @type {Map<string, number>}
39
+ * Stores TTL (in ms) for each groupId individually
39
40
  */
40
- getInterval(): number;
41
+ groupTTL: Map<string, number>;
41
42
  /**
42
- * Get the maximum number of allowed hits.
43
+ * Set the callback to be triggered when a group exceeds its limit
44
+ * @param {OnMemoryExceeded} callback
45
+ */
46
+ setOnMemoryExceeded(callback: OnMemoryExceeded): void;
47
+ /**
48
+ * Clear the onMemoryExceeded callback
49
+ */
50
+ clearOnMemoryExceeded(): void;
51
+ /**
52
+ * Set the callback to be triggered when a group expires and is removed.
43
53
  *
44
- * @returns {number} The maxHits value.
45
- * @throws {Error} If maxHits is not a valid finite number.
54
+ * This callback is called automatically during cleanup when a group
55
+ * becomes inactive for longer than its TTL.
56
+ *
57
+ * @param {OnGroupExpired} callback - A function that receives the expired groupId.
46
58
  */
47
- getMaxHits(): number;
59
+ setOnGroupExpired(callback: OnGroupExpired): void;
60
+ /**
61
+ * Clear the onGroupExpired callback
62
+ */
63
+ clearOnGroupExpired(): void;
64
+ /**
65
+ * Check if a given ID is a groupId (not a userId)
66
+ * @param {string} id
67
+ * @returns {boolean}
68
+ */
69
+ isGroupId(id: string): boolean;
70
+ /**
71
+ * Get all user IDs that belong to a given group.
72
+ * @param {string} groupId
73
+ * @returns {string[]}
74
+ */
75
+ getUsersInGroup(groupId: string): string[];
76
+ /**
77
+ * Set TTL (in milliseconds) for a specific group
78
+ * @param {string} groupId
79
+ * @param {number} ttl
80
+ */
81
+ setGroupTTL(groupId: string, ttl: number): void;
82
+ /**
83
+ * Get TTL (in ms) for a specific group.
84
+ * @param {string} groupId
85
+ * @returns {number|null}
86
+ */
87
+ getGroupTTL(groupId: string): number | null;
88
+ /**
89
+ * Delete the TTL setting for a specific group
90
+ * @param {string} groupId
91
+ */
92
+ deleteGroupTTL(groupId: string): void;
93
+ /**
94
+ * Assign a userId to a groupId, with merge if user has existing data.
95
+ * @param {string} userId
96
+ * @param {string} groupId
97
+ * @throws {Error} If userId is already assigned to a different group
98
+ */
99
+ assignToGroup(userId: string, groupId: string): void;
100
+ /**
101
+ * Get the groupId for a given userId
102
+ * @param {string} userId
103
+ * @returns {string}
104
+ */
105
+ getGroupId(userId: string): string;
48
106
  /**
49
107
  * Register a hit for a specific user
50
108
  * @param {string} userId
51
109
  */
52
110
  hit(userId: string): void;
53
111
  /**
54
- * Check if the user is currently rate limited
112
+ * Check if the user (via their group) is currently rate limited
55
113
  * @param {string} userId
56
114
  * @returns {boolean}
57
115
  */
58
116
  isRateLimited(userId: string): boolean;
59
117
  /**
60
- * Manually reset user data
118
+ * Manually reset group data
119
+ * @param {string} groupId
120
+ */
121
+ resetGroup(groupId: string): void;
122
+ /**
123
+ * Manually reset user data.
124
+ *
125
+ * @deprecated Use `resetUserGroup(userId)` instead. This method will be removed in future versions.
61
126
  * @param {string} userId
127
+ * @returns {void}
62
128
  */
63
129
  reset(userId: string): void;
64
130
  /**
65
- * Set hit timestamps for a user
131
+ * Manually reset a user mapping
66
132
  * @param {string} userId
133
+ */
134
+ resetUserGroup(userId: string): void;
135
+ /**
136
+ * Set custom timestamps to a group
137
+ * @param {string} groupId
67
138
  * @param {number[]} timestamps
68
139
  */
69
- setData(userId: string, timestamps: number[]): void;
140
+ setData(groupId: string, timestamps: number[]): void;
70
141
  /**
71
- * Get timestamps from user
72
- * @param {string} userId
142
+ * Check if a group has data
143
+ * @param {string} groupId
144
+ * @returns {boolean}
145
+ */
146
+ hasData(groupId: string): boolean;
147
+ /**
148
+ * Get timestamps from a group
149
+ * @param {string} groupId
73
150
  * @returns {number[]}
74
151
  */
75
- getData(userId: string): number[];
152
+ getData(groupId: string): number[];
153
+ /**
154
+ * Get the maximum idle time (in milliseconds) before a group is considered expired.
155
+ * @returns {number}
156
+ */
157
+ getMaxIdle(): number;
158
+ /**
159
+ * Set the maximum idle time (in milliseconds) before a group is considered expired.
160
+ * @param {number} ms
161
+ */
162
+ setMaxIdle(ms: number): void;
76
163
  /**
77
- * Cleanup old/inactive users
164
+ * Cleanup old/inactive groups with individual TTLs
78
165
  * @private
79
166
  */
80
167
  private _cleanup;
81
168
  /**
82
- * Destroy the rate limiter, stopping all intervals
169
+ * Get list of active group IDs
170
+ * @returns {string[]}
171
+ */
172
+ getActiveGroups(): string[];
173
+ /**
174
+ * Get a shallow copy of all user-to-group mappings as a plain object
175
+ * @returns {Record<string, string>}
176
+ */
177
+ getAllUserMappings(): Record<string, string>;
178
+ /**
179
+ * Get the interval window in milliseconds.
180
+ * @returns {number}
181
+ */
182
+ getInterval(): number;
183
+ /**
184
+ * Get the maximum number of allowed hits.
185
+ * @returns {number}
186
+ */
187
+ getMaxHits(): number;
188
+ /**
189
+ * Get the total number of hits recorded for a group.
190
+ * @param {string} groupId
191
+ * @returns {number}
192
+ */
193
+ getTotalHits(groupId: string): number;
194
+ /**
195
+ * Get the timestamp of the last hit for a group.
196
+ * @param {string} groupId
197
+ * @returns {number|null}
198
+ */
199
+ getLastHit(groupId: string): number | null;
200
+ /**
201
+ * Get milliseconds since the last hit for a group.
202
+ * @param {string} groupId
203
+ * @returns {number|null}
204
+ */
205
+ getTimeSinceLastHit(groupId: string): number | null;
206
+ /**
207
+ * Internal utility to compute average spacing
208
+ * @private
209
+ * @param {number[]|undefined} history
210
+ * @returns {number|null}
211
+ */
212
+ private _calculateAverageSpacing;
213
+ /**
214
+ * Get average time between hits for a group (ms).
215
+ * @param {string} groupId
216
+ * @returns {number|null}
217
+ */
218
+ getAverageHitSpacing(groupId: string): number | null;
219
+ /**
220
+ * Get metrics about a group's activity.
221
+ * @param {string} groupId
222
+ * @returns {{
223
+ * totalHits: number,
224
+ * lastHit: number|null,
225
+ * timeSinceLastHit: number|null,
226
+ * averageHitSpacing: number|null
227
+ * }}
228
+ */
229
+ getMetrics(groupId: string): {
230
+ totalHits: number;
231
+ lastHit: number | null;
232
+ timeSinceLastHit: number | null;
233
+ averageHitSpacing: number | null;
234
+ };
235
+ /**
236
+ * Destroy the rate limiter, stopping cleanup and clearing data
83
237
  */
84
238
  destroy(): void;
239
+ #private;
85
240
  }
86
241
  //# sourceMappingURL=TinyRateLimiter.d.mts.map