lunibee 0.2.3 → 0.2.4
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/LICENSE +21 -21
- package/README.md +225 -225
- package/dist/builders/attachment.d.ts +8 -0
- package/dist/builders/commands.d.ts +122 -65
- package/dist/builders/components.d.ts +10 -31
- package/dist/builders/embed.d.ts +66 -33
- package/dist/builders/index.js +97 -131
- package/dist/builders/index.js.map +8 -8
- package/dist/collection/cache.d.ts +13 -6
- package/dist/collection/index.d.ts +90 -17
- package/dist/collection/index.js +442 -266
- package/dist/collection/index.js.map +4 -4
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +607 -352
- package/dist/core/index.js.map +47 -47
- package/dist/core/permissions.d.ts +7 -3
- package/dist/formatters/index.js +9 -5
- package/dist/formatters/index.js.map +3 -3
- package/dist/handlers/index.js +5 -10
- package/dist/handlers/index.js.map +3 -3
- package/dist/index.js +769 -587
- package/dist/index.js.map +65 -65
- package/dist/managers/base.d.ts +22 -14
- package/dist/managers/index.d.ts +2 -1
- package/dist/managers/index.js +445 -276
- package/dist/managers/index.js.map +26 -26
- package/dist/managers/message.d.ts +7 -3
- package/dist/rest/errors.d.ts +14 -7
- package/dist/rest/index.d.ts +24 -12
- package/dist/rest/index.js +54 -17
- package/dist/rest/index.js.map +14 -14
- package/dist/rest/redis.d.ts +1 -1
- package/dist/rest/route.d.ts +8 -4
- package/dist/rest/routes.d.ts +102 -48
- package/dist/rest/transport.d.ts +10 -5
- package/dist/rest/webhook.d.ts +9 -5
- package/dist/sharding/bus.d.ts +34 -17
- package/dist/sharding/index.d.ts +34 -17
- package/dist/sharding/index.js +64 -32
- package/dist/sharding/index.js.map +17 -17
- package/dist/structures/base.d.ts +19 -10
- package/dist/structures/channels.d.ts +28 -14
- package/dist/structures/index.js +9 -59
- package/dist/structures/index.js.map +19 -18
- package/dist/structures/interactions.d.ts +96 -48
- package/dist/structures/resources.d.ts +88 -44
- package/dist/types/gateway.d.ts +1 -1
- package/dist/types/index.js +20 -22
- package/dist/types/index.js.map +4 -4
- package/dist/utils/index.js.map +2 -2
- package/dist/voice/index.d.ts +12 -4
- package/dist/voice/index.js +14 -18
- package/dist/voice/index.js.map +3 -3
- package/dist/ws/decoder.d.ts +6 -2
- package/dist/ws/index.d.ts +25 -13
- package/dist/ws/index.js +63 -31
- package/dist/ws/index.js.map +14 -14
- package/dist/ws/protocol.d.ts +10 -2
- package/dist/ws/session.d.ts +14 -4
- package/dist/ws/state.d.ts +22 -11
- package/package.json +15 -14
package/dist/collection/index.js
CHANGED
|
@@ -1,64 +1,36 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/collection/src/cache.ts
|
|
3
3
|
class Cache {
|
|
4
|
-
#entries
|
|
5
|
-
#maxSize;
|
|
6
|
-
#ttl;
|
|
7
|
-
#timer;
|
|
4
|
+
#entries;
|
|
8
5
|
constructor(options = {}) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (!Number.isInteger(
|
|
6
|
+
const maxSize = options.maxSize ?? Infinity;
|
|
7
|
+
const ttl = options.ttl ?? 0;
|
|
8
|
+
if (!Number.isInteger(maxSize) && maxSize !== Infinity || maxSize < 1)
|
|
12
9
|
throw new RangeError("Cache maxSize must be a positive integer.");
|
|
13
|
-
if (!Number.isFinite(
|
|
10
|
+
if (!Number.isFinite(ttl) || ttl < 0)
|
|
14
11
|
throw new RangeError("Cache ttl must be a non-negative finite number.");
|
|
15
|
-
if (
|
|
16
|
-
const interval = options.sweepInterval ?? Math.min(
|
|
12
|
+
if (ttl > 0) {
|
|
13
|
+
const interval = options.sweepInterval ?? Math.min(ttl, 60000);
|
|
17
14
|
if (!Number.isFinite(interval) || interval < 1)
|
|
18
15
|
throw new RangeError("Cache sweepInterval must be positive.");
|
|
19
|
-
this.#timer = setInterval(() => this.sweep(), interval);
|
|
20
|
-
this.#timer.unref?.();
|
|
21
16
|
}
|
|
17
|
+
this.#entries = new Collection(null, {
|
|
18
|
+
ttl: ttl > 0 ? ttl : undefined,
|
|
19
|
+
maxSize: maxSize === Infinity ? undefined : maxSize,
|
|
20
|
+
slide: false
|
|
21
|
+
});
|
|
22
22
|
}
|
|
23
23
|
get size() {
|
|
24
|
-
this.#sweepExpired();
|
|
25
24
|
return this.#entries.size;
|
|
26
25
|
}
|
|
27
26
|
get(key) {
|
|
28
|
-
|
|
29
|
-
if (!entry)
|
|
30
|
-
return;
|
|
31
|
-
if (entry.expiresAt > 0 && entry.expiresAt <= Date.now()) {
|
|
32
|
-
this.#entries.delete(key);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
this.#entries.delete(key);
|
|
36
|
-
this.#entries.set(key, entry);
|
|
37
|
-
return entry.value;
|
|
27
|
+
return this.#entries.get(key);
|
|
38
28
|
}
|
|
39
29
|
has(key) {
|
|
40
|
-
|
|
41
|
-
if (!entry)
|
|
42
|
-
return false;
|
|
43
|
-
if (entry.expiresAt > 0 && entry.expiresAt <= Date.now()) {
|
|
44
|
-
this.#entries.delete(key);
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
return true;
|
|
30
|
+
return this.#entries.has(key);
|
|
48
31
|
}
|
|
49
32
|
set(key, value) {
|
|
50
|
-
|
|
51
|
-
this.#entries.delete(key);
|
|
52
|
-
this.#entries.set(key, { value, expiresAt });
|
|
53
|
-
if (this.#maxSize !== Infinity) {
|
|
54
|
-
while (this.#entries.size > this.#maxSize) {
|
|
55
|
-
const oldest = this.#entries.firstKey();
|
|
56
|
-
if (oldest !== undefined)
|
|
57
|
-
this.#entries.delete(oldest);
|
|
58
|
-
else
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
33
|
+
this.#entries.set(key, value);
|
|
62
34
|
return this;
|
|
63
35
|
}
|
|
64
36
|
delete(key) {
|
|
@@ -68,95 +40,52 @@ class Cache {
|
|
|
68
40
|
this.#entries.clear();
|
|
69
41
|
}
|
|
70
42
|
invalidate(predicate) {
|
|
71
|
-
return this.#entries.sweep(
|
|
43
|
+
return this.#entries.sweep(predicate);
|
|
72
44
|
}
|
|
73
45
|
sweep() {
|
|
74
|
-
return this.#entries.
|
|
75
|
-
}
|
|
76
|
-
dispose() {
|
|
77
|
-
if (this.#timer)
|
|
78
|
-
clearInterval(this.#timer);
|
|
79
|
-
this.#timer = undefined;
|
|
46
|
+
return this.#entries.purge();
|
|
80
47
|
}
|
|
48
|
+
dispose() {}
|
|
81
49
|
values() {
|
|
82
|
-
this.#
|
|
83
|
-
return this.#entries.map((entry) => entry.value);
|
|
50
|
+
return [...this.#entries.values()];
|
|
84
51
|
}
|
|
85
52
|
entries() {
|
|
86
|
-
this.#
|
|
87
|
-
return this.#entries.map((entry, key) => [key, entry.value]);
|
|
88
|
-
}
|
|
89
|
-
#expired(entry) {
|
|
90
|
-
return entry.expiresAt > 0 && entry.expiresAt <= Date.now();
|
|
91
|
-
}
|
|
92
|
-
#sweepExpired() {
|
|
93
|
-
if (this.#ttl > 0)
|
|
94
|
-
this.sweep();
|
|
53
|
+
return [...this.#entries.entries()];
|
|
95
54
|
}
|
|
96
55
|
}
|
|
97
56
|
|
|
98
57
|
// packages/collection/src/index.ts
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this.#unlink(node);
|
|
131
|
-
this.#nodes.delete(key);
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
clear() {
|
|
135
|
-
this.#nodes.clear();
|
|
136
|
-
this.#oldest = this.#newest = undefined;
|
|
137
|
-
}
|
|
138
|
-
#unlink(node) {
|
|
139
|
-
if (node.older)
|
|
140
|
-
node.older.newer = node.newer;
|
|
141
|
-
else
|
|
142
|
-
this.#oldest = node.newer;
|
|
143
|
-
if (node.newer)
|
|
144
|
-
node.newer.older = node.older;
|
|
145
|
-
else
|
|
146
|
-
this.#newest = node.older;
|
|
147
|
-
node.older = node.newer = undefined;
|
|
148
|
-
}
|
|
149
|
-
#moveNewest(node) {
|
|
150
|
-
if (node === this.#newest)
|
|
151
|
-
return;
|
|
152
|
-
this.#unlink(node);
|
|
153
|
-
node.older = this.#newest;
|
|
154
|
-
if (this.#newest)
|
|
155
|
-
this.#newest.newer = node;
|
|
156
|
-
else
|
|
157
|
-
this.#oldest = node;
|
|
158
|
-
this.#newest = node;
|
|
159
|
-
}
|
|
58
|
+
function newPolicy(options = {}) {
|
|
59
|
+
return {
|
|
60
|
+
ttl: options.ttl,
|
|
61
|
+
maxSize: options.maxSize,
|
|
62
|
+
slide: options.slide ?? true,
|
|
63
|
+
onEvict: options.onEvict,
|
|
64
|
+
expired: 0,
|
|
65
|
+
evicted: 0,
|
|
66
|
+
entries: new Map,
|
|
67
|
+
oldest: undefined,
|
|
68
|
+
newest: undefined,
|
|
69
|
+
lruSize: 0,
|
|
70
|
+
heap: [],
|
|
71
|
+
armedFor: Infinity
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function peekOf(collection, key) {
|
|
75
|
+
return collection instanceof Map ? Map.prototype.get.call(collection, key) : collection.get(key);
|
|
76
|
+
}
|
|
77
|
+
var mapGet = Map.prototype.get;
|
|
78
|
+
var mapHas = Map.prototype.has;
|
|
79
|
+
function sample(items, amount) {
|
|
80
|
+
if (!Number.isInteger(amount) || amount < 0)
|
|
81
|
+
throw new RangeError("amount must be a non-negative integer.");
|
|
82
|
+
const count = Math.min(amount, items.length);
|
|
83
|
+
for (let i = 0;i < count; i++) {
|
|
84
|
+
const j = i + Math.floor(Math.random() * (items.length - i));
|
|
85
|
+
[items[i], items[j]] = [items[j], items[i]];
|
|
86
|
+
}
|
|
87
|
+
items.length = count;
|
|
88
|
+
return items;
|
|
160
89
|
}
|
|
161
90
|
function assertTTL(ttl) {
|
|
162
91
|
if (ttl !== undefined && (!Number.isFinite(ttl) || ttl <= 0))
|
|
@@ -164,81 +93,90 @@ function assertTTL(ttl) {
|
|
|
164
93
|
}
|
|
165
94
|
|
|
166
95
|
class Collection extends Map {
|
|
167
|
-
#
|
|
168
|
-
#
|
|
169
|
-
#
|
|
170
|
-
#expiry = new Map;
|
|
171
|
-
#lru = new RecencyList;
|
|
172
|
-
#stats = {
|
|
173
|
-
hits: 0,
|
|
174
|
-
misses: 0,
|
|
175
|
-
expired: 0,
|
|
176
|
-
evicted: 0
|
|
177
|
-
};
|
|
178
|
-
#heap = [];
|
|
179
|
-
#timer;
|
|
180
|
-
#armedFor = Infinity;
|
|
96
|
+
#policy;
|
|
97
|
+
#hits = 0;
|
|
98
|
+
#misses = 0;
|
|
181
99
|
constructor(entries, options = {}) {
|
|
182
100
|
super();
|
|
183
101
|
assertTTL(options.ttl);
|
|
184
102
|
if (options.maxSize !== undefined && (!Number.isInteger(options.maxSize) || options.maxSize <= 0))
|
|
185
103
|
throw new RangeError("maxSize must be a positive integer.");
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
this.#onEvict = options.onEvict;
|
|
104
|
+
if (options.ttl !== undefined || options.maxSize !== undefined || options.slide !== undefined || options.onEvict !== undefined)
|
|
105
|
+
this.#policy = newPolicy(options);
|
|
189
106
|
if (entries)
|
|
190
107
|
for (const [key, value] of entries)
|
|
191
108
|
this.set(key, value);
|
|
192
109
|
}
|
|
193
110
|
set(key, value, ttl) {
|
|
111
|
+
if (ttl === undefined && this.#policy === undefined)
|
|
112
|
+
return super.set(key, value);
|
|
194
113
|
assertTTL(ttl);
|
|
195
|
-
const window = ttl ?? this.#ttl;
|
|
196
|
-
if (this.#maxSize !== undefined) {
|
|
197
|
-
this.#lru.touch(key);
|
|
198
|
-
}
|
|
199
|
-
super.set(key, value);
|
|
114
|
+
const window = ttl ?? this.#policy?.ttl;
|
|
200
115
|
if (window !== undefined)
|
|
201
|
-
this.#
|
|
202
|
-
|
|
203
|
-
|
|
116
|
+
this.#policy ??= newPolicy();
|
|
117
|
+
if (!this.#policy)
|
|
118
|
+
return super.set(key, value);
|
|
119
|
+
const before = super.size;
|
|
120
|
+
super.set(key, value);
|
|
121
|
+
this.#track(key, value, window, super.size !== before);
|
|
204
122
|
this.#enforceCap();
|
|
205
123
|
return this;
|
|
206
124
|
}
|
|
207
125
|
setWithoutTTL(key, value) {
|
|
208
|
-
if (this.#
|
|
209
|
-
this.#
|
|
210
|
-
if (this.#lru.size > 0)
|
|
211
|
-
this.#lru.delete(key);
|
|
126
|
+
if (this.#policy)
|
|
127
|
+
this.#forget(key);
|
|
212
128
|
super.set(key, value);
|
|
213
129
|
return this;
|
|
214
130
|
}
|
|
215
131
|
get(key) {
|
|
216
|
-
|
|
217
|
-
|
|
132
|
+
const policy = this.#policy;
|
|
133
|
+
const entry = policy?.entries.get(key);
|
|
134
|
+
if (entry === undefined) {
|
|
135
|
+
const value = mapGet.call(this, key);
|
|
136
|
+
if (value !== undefined || mapHas.call(this, key)) {
|
|
137
|
+
this.#hits++;
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
this.#misses++;
|
|
218
141
|
return;
|
|
219
142
|
}
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
143
|
+
const timed = entry.window !== 0;
|
|
144
|
+
const now = timed ? Date.now() : 0;
|
|
145
|
+
if (timed && entry.deadline <= now) {
|
|
146
|
+
this.#expire(entry);
|
|
147
|
+
this.#misses++;
|
|
223
148
|
return;
|
|
224
149
|
}
|
|
225
|
-
this.#
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return value;
|
|
150
|
+
this.#hits++;
|
|
151
|
+
if (timed && policy.slide)
|
|
152
|
+
entry.deadline = now + entry.window;
|
|
153
|
+
if (entry.inLru)
|
|
154
|
+
this.#promote(policy, entry);
|
|
155
|
+
return entry.value;
|
|
156
|
+
}
|
|
157
|
+
ensure(key, factory, ttl) {
|
|
158
|
+
const existing = this.get(key);
|
|
159
|
+
if (existing !== undefined || super.has(key))
|
|
160
|
+
return existing;
|
|
161
|
+
const created = factory(key, this);
|
|
162
|
+
this.set(key, created, ttl);
|
|
163
|
+
return created;
|
|
231
164
|
}
|
|
232
165
|
peek(key) {
|
|
233
166
|
if (!this.#expireIfDue(key) && super.has(key)) {
|
|
234
|
-
this.#
|
|
167
|
+
this.#hits++;
|
|
235
168
|
return super.get(key);
|
|
236
169
|
}
|
|
237
|
-
this.#
|
|
170
|
+
this.#misses++;
|
|
238
171
|
return;
|
|
239
172
|
}
|
|
240
173
|
get stats() {
|
|
241
|
-
return {
|
|
174
|
+
return {
|
|
175
|
+
hits: this.#hits,
|
|
176
|
+
misses: this.#misses,
|
|
177
|
+
expired: this.#policy?.expired ?? 0,
|
|
178
|
+
evicted: this.#policy?.evicted ?? 0
|
|
179
|
+
};
|
|
242
180
|
}
|
|
243
181
|
has(key) {
|
|
244
182
|
return !this.#expireIfDue(key) && super.has(key);
|
|
@@ -246,19 +184,23 @@ class Collection extends Map {
|
|
|
246
184
|
delete(key) {
|
|
247
185
|
if (this.#expireIfDue(key))
|
|
248
186
|
return false;
|
|
249
|
-
this.#
|
|
250
|
-
|
|
187
|
+
if (this.#policy)
|
|
188
|
+
this.#forget(key);
|
|
251
189
|
return super.delete(key);
|
|
252
190
|
}
|
|
253
191
|
clear() {
|
|
254
192
|
super.clear();
|
|
255
|
-
this.#
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
193
|
+
const policy = this.#policy;
|
|
194
|
+
if (!policy)
|
|
195
|
+
return;
|
|
196
|
+
policy.entries.clear();
|
|
197
|
+
policy.oldest = policy.newest = undefined;
|
|
198
|
+
policy.lruSize = 0;
|
|
199
|
+
policy.heap.length = 0;
|
|
200
|
+
if (policy.timer)
|
|
201
|
+
clearTimeout(policy.timer);
|
|
202
|
+
policy.timer = undefined;
|
|
203
|
+
policy.armedFor = Infinity;
|
|
262
204
|
}
|
|
263
205
|
get size() {
|
|
264
206
|
this.purge();
|
|
@@ -286,11 +228,11 @@ class Collection extends Map {
|
|
|
286
228
|
ttlRemaining(key) {
|
|
287
229
|
if (this.#expireIfDue(key))
|
|
288
230
|
return;
|
|
289
|
-
const
|
|
290
|
-
return
|
|
231
|
+
const entry = this.#policy?.entries.get(key);
|
|
232
|
+
return entry && entry.window !== 0 ? Math.max(0, entry.deadline - Date.now()) : undefined;
|
|
291
233
|
}
|
|
292
234
|
purge() {
|
|
293
|
-
if (this.#
|
|
235
|
+
if (!this.#policy || this.#policy.heap.length === 0)
|
|
294
236
|
return 0;
|
|
295
237
|
const now = Date.now();
|
|
296
238
|
let removed = 0;
|
|
@@ -301,133 +243,255 @@ class Collection extends Map {
|
|
|
301
243
|
this.#remove(due.key);
|
|
302
244
|
removed++;
|
|
303
245
|
}
|
|
304
|
-
this.#
|
|
246
|
+
this.#policy.expired += removed;
|
|
305
247
|
this.#rearm();
|
|
306
248
|
for (const [key, value] of dropped)
|
|
307
249
|
this.#notify(key, value, "expired");
|
|
308
250
|
return removed;
|
|
309
251
|
}
|
|
310
252
|
#expireIfDue(key) {
|
|
311
|
-
const
|
|
312
|
-
if (!
|
|
253
|
+
const entry = this.#policy?.entries.get(key);
|
|
254
|
+
if (!entry || entry.window === 0 || entry.deadline > Date.now())
|
|
313
255
|
return false;
|
|
314
|
-
|
|
315
|
-
this.#remove(key);
|
|
316
|
-
this.#stats.expired++;
|
|
317
|
-
this.#notify(key, value, "expired");
|
|
256
|
+
this.#expire(entry);
|
|
318
257
|
return true;
|
|
319
258
|
}
|
|
259
|
+
#expire(entry) {
|
|
260
|
+
const value = super.get(entry.key);
|
|
261
|
+
this.#remove(entry.key);
|
|
262
|
+
this.#policy.expired++;
|
|
263
|
+
this.#notify(entry.key, value, "expired");
|
|
264
|
+
}
|
|
320
265
|
#remove(key) {
|
|
321
|
-
this.#
|
|
322
|
-
this.#lru.delete(key);
|
|
266
|
+
this.#forget(key);
|
|
323
267
|
super.delete(key);
|
|
324
268
|
}
|
|
269
|
+
#forget(key) {
|
|
270
|
+
const policy = this.#policy;
|
|
271
|
+
const entry = policy.entries.get(key);
|
|
272
|
+
if (!entry)
|
|
273
|
+
return;
|
|
274
|
+
if (entry.inLru)
|
|
275
|
+
this.#unlink(policy, entry);
|
|
276
|
+
policy.entries.delete(key);
|
|
277
|
+
}
|
|
278
|
+
#track(key, value, window, isNew) {
|
|
279
|
+
const policy = this.#policy;
|
|
280
|
+
const lru = policy.maxSize !== undefined;
|
|
281
|
+
let entry = isNew ? undefined : policy.entries.get(key);
|
|
282
|
+
if (entry)
|
|
283
|
+
entry.value = value;
|
|
284
|
+
if (window === undefined) {
|
|
285
|
+
if (entry && entry.window !== 0) {
|
|
286
|
+
if (lru)
|
|
287
|
+
entry = this.#replace(policy, entry, 0, 0);
|
|
288
|
+
else {
|
|
289
|
+
this.#forget(key);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (!entry && lru) {
|
|
294
|
+
entry = this.#create(key, value, 0, 0);
|
|
295
|
+
policy.entries.set(key, entry);
|
|
296
|
+
}
|
|
297
|
+
if (entry)
|
|
298
|
+
this.#promote(policy, entry);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const deadline = Date.now() + window;
|
|
302
|
+
if (entry && entry.window !== 0) {
|
|
303
|
+
entry.deadline = deadline;
|
|
304
|
+
entry.window = window;
|
|
305
|
+
if (deadline < entry.filed)
|
|
306
|
+
entry = this.#replace(policy, entry, window, deadline);
|
|
307
|
+
else {
|
|
308
|
+
if (entry.inLru)
|
|
309
|
+
this.#promote(policy, entry);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
} else if (entry) {
|
|
313
|
+
entry.window = window;
|
|
314
|
+
entry.deadline = entry.filed = deadline;
|
|
315
|
+
} else {
|
|
316
|
+
entry = this.#create(key, value, window, deadline);
|
|
317
|
+
policy.entries.set(key, entry);
|
|
318
|
+
}
|
|
319
|
+
if (lru)
|
|
320
|
+
this.#promote(policy, entry);
|
|
321
|
+
this.#heapPush(entry);
|
|
322
|
+
if (policy.heap.length > 2 * policy.entries.size + 8)
|
|
323
|
+
this.#compact();
|
|
324
|
+
if (policy.timer === undefined || deadline < policy.armedFor)
|
|
325
|
+
this.#rearm();
|
|
326
|
+
}
|
|
327
|
+
#create(key, value, window, deadline) {
|
|
328
|
+
return {
|
|
329
|
+
key,
|
|
330
|
+
value,
|
|
331
|
+
older: undefined,
|
|
332
|
+
newer: undefined,
|
|
333
|
+
inLru: false,
|
|
334
|
+
window,
|
|
335
|
+
deadline,
|
|
336
|
+
filed: deadline
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
#replace(policy, old, window, deadline) {
|
|
340
|
+
const entry = {
|
|
341
|
+
...old,
|
|
342
|
+
window,
|
|
343
|
+
deadline,
|
|
344
|
+
filed: deadline
|
|
345
|
+
};
|
|
346
|
+
if (old.inLru) {
|
|
347
|
+
if (old.older)
|
|
348
|
+
old.older.newer = entry;
|
|
349
|
+
else
|
|
350
|
+
policy.oldest = entry;
|
|
351
|
+
if (old.newer)
|
|
352
|
+
old.newer.older = entry;
|
|
353
|
+
else
|
|
354
|
+
policy.newest = entry;
|
|
355
|
+
}
|
|
356
|
+
policy.entries.set(old.key, entry);
|
|
357
|
+
return entry;
|
|
358
|
+
}
|
|
359
|
+
#promote(policy, entry) {
|
|
360
|
+
if (entry === policy.newest)
|
|
361
|
+
return;
|
|
362
|
+
if (entry.inLru)
|
|
363
|
+
this.#unlink(policy, entry, true);
|
|
364
|
+
else {
|
|
365
|
+
entry.inLru = true;
|
|
366
|
+
policy.lruSize++;
|
|
367
|
+
}
|
|
368
|
+
entry.older = policy.newest;
|
|
369
|
+
entry.newer = undefined;
|
|
370
|
+
if (policy.newest)
|
|
371
|
+
policy.newest.newer = entry;
|
|
372
|
+
else
|
|
373
|
+
policy.oldest = entry;
|
|
374
|
+
policy.newest = entry;
|
|
375
|
+
}
|
|
376
|
+
#unlink(policy, entry, keepCount = false) {
|
|
377
|
+
if (entry.older)
|
|
378
|
+
entry.older.newer = entry.newer;
|
|
379
|
+
else
|
|
380
|
+
policy.oldest = entry.newer;
|
|
381
|
+
if (entry.newer)
|
|
382
|
+
entry.newer.older = entry.older;
|
|
383
|
+
else
|
|
384
|
+
policy.newest = entry.older;
|
|
385
|
+
entry.older = entry.newer = undefined;
|
|
386
|
+
if (!keepCount) {
|
|
387
|
+
entry.inLru = false;
|
|
388
|
+
policy.lruSize--;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
#derived() {
|
|
392
|
+
const Species = this.constructor[Symbol.species] ?? Collection;
|
|
393
|
+
return new Species;
|
|
394
|
+
}
|
|
325
395
|
#notify(key, value, reason) {
|
|
326
|
-
|
|
396
|
+
const onEvict = this.#policy?.onEvict;
|
|
397
|
+
if (!onEvict)
|
|
327
398
|
return;
|
|
328
399
|
try {
|
|
329
|
-
|
|
400
|
+
onEvict(key, value, reason);
|
|
330
401
|
} catch {}
|
|
331
402
|
}
|
|
332
403
|
#enforceCap() {
|
|
333
|
-
|
|
404
|
+
const policy = this.#policy;
|
|
405
|
+
const max = policy.maxSize;
|
|
406
|
+
if (max === undefined)
|
|
334
407
|
return;
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
this.#
|
|
408
|
+
if (policy.lruSize > max && policy.heap.length > 0 && policy.heap[0].filed <= Date.now())
|
|
409
|
+
this.purge();
|
|
410
|
+
while (policy.lruSize > max) {
|
|
411
|
+
const oldest = policy.oldest;
|
|
412
|
+
const value = policy.onEvict ? super.get(oldest.key) : undefined;
|
|
413
|
+
this.#unlink(policy, oldest);
|
|
414
|
+
policy.entries.delete(oldest.key);
|
|
415
|
+
super.delete(oldest.key);
|
|
416
|
+
policy.evicted++;
|
|
417
|
+
this.#notify(oldest.key, value, "evicted");
|
|
341
418
|
}
|
|
342
419
|
}
|
|
343
|
-
#schedule(key, window) {
|
|
344
|
-
const deadline = Date.now() + window;
|
|
345
|
-
const expiry = this.#expiry.get(key);
|
|
346
|
-
if (expiry) {
|
|
347
|
-
expiry.deadline = deadline;
|
|
348
|
-
expiry.window = window;
|
|
349
|
-
if (deadline >= expiry.filed)
|
|
350
|
-
return;
|
|
351
|
-
expiry.filed = deadline;
|
|
352
|
-
} else
|
|
353
|
-
this.#expiry.set(key, { deadline, window, filed: deadline });
|
|
354
|
-
this.#heapPush({ key, deadline });
|
|
355
|
-
if (this.#heap.length > 2 * this.#expiry.size + 8)
|
|
356
|
-
this.#compact();
|
|
357
|
-
this.#rearm();
|
|
358
|
-
}
|
|
359
420
|
#nextDeadline() {
|
|
421
|
+
const policy = this.#policy;
|
|
360
422
|
for (;; ) {
|
|
361
|
-
const top =
|
|
423
|
+
const top = policy.heap[0];
|
|
362
424
|
if (top === undefined)
|
|
363
425
|
return Infinity;
|
|
364
|
-
|
|
365
|
-
if (!expiry || expiry.filed !== top.deadline) {
|
|
426
|
+
if (policy.entries.get(top.key) !== top) {
|
|
366
427
|
this.#heapPop();
|
|
367
428
|
continue;
|
|
368
429
|
}
|
|
369
|
-
if (
|
|
370
|
-
return top.
|
|
430
|
+
if (top.deadline === top.filed)
|
|
431
|
+
return top.filed;
|
|
371
432
|
this.#heapPop();
|
|
372
|
-
|
|
373
|
-
this.#heapPush(
|
|
433
|
+
top.filed = top.deadline;
|
|
434
|
+
this.#heapPush(top);
|
|
374
435
|
}
|
|
375
436
|
}
|
|
376
437
|
#compact() {
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
438
|
+
const policy = this.#policy;
|
|
439
|
+
const live = policy.heap.filter((entry) => policy.entries.get(entry.key) === entry);
|
|
440
|
+
policy.heap.length = 0;
|
|
441
|
+
for (const entry of live)
|
|
442
|
+
this.#heapPush(entry);
|
|
381
443
|
}
|
|
382
444
|
#rearm() {
|
|
445
|
+
const p = this.#policy;
|
|
383
446
|
const deadline = this.#nextDeadline();
|
|
384
|
-
if (
|
|
447
|
+
if (p.timer !== undefined && deadline >= p.armedFor)
|
|
385
448
|
return;
|
|
386
|
-
if (
|
|
387
|
-
clearTimeout(
|
|
388
|
-
|
|
389
|
-
|
|
449
|
+
if (p.timer)
|
|
450
|
+
clearTimeout(p.timer);
|
|
451
|
+
p.timer = undefined;
|
|
452
|
+
p.armedFor = deadline;
|
|
390
453
|
if (deadline === Infinity)
|
|
391
454
|
return;
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
455
|
+
p.timer = setTimeout(() => {
|
|
456
|
+
p.timer = undefined;
|
|
457
|
+
p.armedFor = Infinity;
|
|
395
458
|
this.purge();
|
|
396
459
|
}, Math.max(0, deadline - Date.now()));
|
|
397
|
-
|
|
460
|
+
p.timer.unref?.();
|
|
398
461
|
}
|
|
399
|
-
#heapPush(
|
|
400
|
-
const heap = this.#heap;
|
|
401
|
-
heap.
|
|
402
|
-
|
|
462
|
+
#heapPush(entry) {
|
|
463
|
+
const heap = this.#policy.heap;
|
|
464
|
+
let i = heap.length;
|
|
465
|
+
heap.push(entry);
|
|
403
466
|
while (i > 0) {
|
|
404
467
|
const parent = i - 1 >> 1;
|
|
405
|
-
|
|
468
|
+
const above = heap[parent];
|
|
469
|
+
if (above.filed <= entry.filed)
|
|
406
470
|
break;
|
|
407
|
-
|
|
471
|
+
heap[i] = above;
|
|
408
472
|
i = parent;
|
|
409
473
|
}
|
|
474
|
+
heap[i] = entry;
|
|
410
475
|
}
|
|
411
476
|
#heapPop() {
|
|
412
|
-
const heap = this.#heap;
|
|
477
|
+
const heap = this.#policy.heap;
|
|
413
478
|
const top = heap[0];
|
|
414
479
|
const last = heap.pop();
|
|
415
480
|
if (top === undefined || heap.length === 0)
|
|
416
481
|
return top;
|
|
417
|
-
|
|
418
|
-
for (
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
let smallest = i;
|
|
422
|
-
if (left < heap.length && heap[left].deadline < heap[smallest].deadline)
|
|
423
|
-
smallest = left;
|
|
424
|
-
if (right < heap.length && heap[right].deadline < heap[smallest].deadline)
|
|
425
|
-
smallest = right;
|
|
426
|
-
if (smallest === i)
|
|
482
|
+
let i = 0;
|
|
483
|
+
for (;; ) {
|
|
484
|
+
let child = 2 * i + 1;
|
|
485
|
+
if (child >= heap.length)
|
|
427
486
|
break;
|
|
428
|
-
|
|
429
|
-
|
|
487
|
+
if (child + 1 < heap.length && heap[child + 1].filed < heap[child].filed)
|
|
488
|
+
child++;
|
|
489
|
+
if (heap[child].filed >= last.filed)
|
|
490
|
+
break;
|
|
491
|
+
heap[i] = heap[child];
|
|
492
|
+
i = child;
|
|
430
493
|
}
|
|
494
|
+
heap[i] = last;
|
|
431
495
|
return top;
|
|
432
496
|
}
|
|
433
497
|
first() {
|
|
@@ -459,8 +523,26 @@ class Collection extends Map {
|
|
|
459
523
|
}
|
|
460
524
|
return;
|
|
461
525
|
}
|
|
526
|
+
findLast(predicate) {
|
|
527
|
+
const entries = [...this];
|
|
528
|
+
for (let i = entries.length - 1;i >= 0; i--) {
|
|
529
|
+
const [key, value] = entries[i];
|
|
530
|
+
if (predicate(value, key, this))
|
|
531
|
+
return value;
|
|
532
|
+
}
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
findLastKey(predicate) {
|
|
536
|
+
const entries = [...this];
|
|
537
|
+
for (let i = entries.length - 1;i >= 0; i--) {
|
|
538
|
+
const [key, value] = entries[i];
|
|
539
|
+
if (predicate(value, key, this))
|
|
540
|
+
return key;
|
|
541
|
+
}
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
462
544
|
filter(predicate) {
|
|
463
|
-
const result =
|
|
545
|
+
const result = this.#derived();
|
|
464
546
|
for (const [key, value] of this) {
|
|
465
547
|
if (predicate(value, key, this))
|
|
466
548
|
result.set(key, value);
|
|
@@ -504,7 +586,7 @@ class Collection extends Map {
|
|
|
504
586
|
return [...this.entries()];
|
|
505
587
|
}
|
|
506
588
|
clone() {
|
|
507
|
-
const copy =
|
|
589
|
+
const copy = this.#derived();
|
|
508
590
|
for (const [key, value] of this)
|
|
509
591
|
copy.set(key, value);
|
|
510
592
|
return copy;
|
|
@@ -559,7 +641,7 @@ class Collection extends Map {
|
|
|
559
641
|
return result;
|
|
560
642
|
}
|
|
561
643
|
intersection(other) {
|
|
562
|
-
const result =
|
|
644
|
+
const result = this.#derived();
|
|
563
645
|
for (const [key, value] of this) {
|
|
564
646
|
if (other.has(key))
|
|
565
647
|
result.set(key, value);
|
|
@@ -567,7 +649,7 @@ class Collection extends Map {
|
|
|
567
649
|
return result;
|
|
568
650
|
}
|
|
569
651
|
difference(other) {
|
|
570
|
-
const result =
|
|
652
|
+
const result = this.#derived();
|
|
571
653
|
for (const [key, value] of this) {
|
|
572
654
|
if (!other.has(key))
|
|
573
655
|
result.set(key, value);
|
|
@@ -575,8 +657,8 @@ class Collection extends Map {
|
|
|
575
657
|
return result;
|
|
576
658
|
}
|
|
577
659
|
partition(predicate) {
|
|
578
|
-
const pass =
|
|
579
|
-
const fail =
|
|
660
|
+
const pass = this.#derived();
|
|
661
|
+
const fail = this.#derived();
|
|
580
662
|
for (const [key, value] of this) {
|
|
581
663
|
if (predicate(value, key, this))
|
|
582
664
|
pass.set(key, value);
|
|
@@ -585,6 +667,81 @@ class Collection extends Map {
|
|
|
585
667
|
}
|
|
586
668
|
return [pass, fail];
|
|
587
669
|
}
|
|
670
|
+
symmetricDifference(other) {
|
|
671
|
+
const result = this.#derived();
|
|
672
|
+
for (const [key, value] of this)
|
|
673
|
+
if (!other.has(key))
|
|
674
|
+
result.set(key, value);
|
|
675
|
+
for (const [key, value] of other)
|
|
676
|
+
if (!this.has(key))
|
|
677
|
+
result.set(key, value);
|
|
678
|
+
return result;
|
|
679
|
+
}
|
|
680
|
+
concat(...collections) {
|
|
681
|
+
const result = this.clone();
|
|
682
|
+
for (const collection of collections)
|
|
683
|
+
for (const [key, value] of collection)
|
|
684
|
+
result.set(key, value);
|
|
685
|
+
return result;
|
|
686
|
+
}
|
|
687
|
+
merge(other, whenInSelf, whenInOther, whenInBoth) {
|
|
688
|
+
const result = this.#derived();
|
|
689
|
+
const decide = (key, kept) => {
|
|
690
|
+
if (kept.keep)
|
|
691
|
+
result.set(key, kept.value);
|
|
692
|
+
};
|
|
693
|
+
for (const [key, value] of this) {
|
|
694
|
+
decide(key, other.has(key) ? whenInBoth(value, peekOf(other, key), key) : whenInSelf(value, key));
|
|
695
|
+
}
|
|
696
|
+
for (const [key, value] of other)
|
|
697
|
+
if (!this.has(key))
|
|
698
|
+
decide(key, whenInOther(value, key));
|
|
699
|
+
return result;
|
|
700
|
+
}
|
|
701
|
+
equals(other) {
|
|
702
|
+
if (!other)
|
|
703
|
+
return false;
|
|
704
|
+
if (other === this)
|
|
705
|
+
return true;
|
|
706
|
+
if (this.size !== other.size)
|
|
707
|
+
return false;
|
|
708
|
+
for (const [key, value] of this) {
|
|
709
|
+
if (!other.has(key))
|
|
710
|
+
return false;
|
|
711
|
+
if (value !== peekOf(other, key))
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
return true;
|
|
715
|
+
}
|
|
716
|
+
mapValues(transform) {
|
|
717
|
+
const result = this.#derived();
|
|
718
|
+
for (const [key, value] of this)
|
|
719
|
+
result.set(key, transform(value, key, this));
|
|
720
|
+
return result;
|
|
721
|
+
}
|
|
722
|
+
toReversed() {
|
|
723
|
+
const result = this.#derived();
|
|
724
|
+
const entries = [...this];
|
|
725
|
+
for (let i = entries.length - 1;i >= 0; i--)
|
|
726
|
+
result.set(entries[i][0], entries[i][1]);
|
|
727
|
+
return result;
|
|
728
|
+
}
|
|
729
|
+
toSorted(comparator) {
|
|
730
|
+
return this.sorted(comparator);
|
|
731
|
+
}
|
|
732
|
+
static groupBy(items, keySelector) {
|
|
733
|
+
const groups = new Collection;
|
|
734
|
+
let index = 0;
|
|
735
|
+
for (const item of items)
|
|
736
|
+
groups.ensure(keySelector(item, index++), () => []).push(item);
|
|
737
|
+
return groups;
|
|
738
|
+
}
|
|
739
|
+
static combineEntries(entries, combine) {
|
|
740
|
+
const result = new Collection;
|
|
741
|
+
for (const [key, value] of entries)
|
|
742
|
+
result.set(key, result.has(key) ? combine(result.get(key), value, key) : value);
|
|
743
|
+
return result;
|
|
744
|
+
}
|
|
588
745
|
tap(fn) {
|
|
589
746
|
fn(this);
|
|
590
747
|
return this;
|
|
@@ -603,6 +760,13 @@ class Collection extends Map {
|
|
|
603
760
|
acc = fn(acc, value, key, this);
|
|
604
761
|
return acc;
|
|
605
762
|
}
|
|
763
|
+
reduceRight(fn, initialValue) {
|
|
764
|
+
const entries = [...this];
|
|
765
|
+
let acc = initialValue;
|
|
766
|
+
for (let i = entries.length - 1;i >= 0; i--)
|
|
767
|
+
acc = fn(acc, entries[i][1], entries[i][0], this);
|
|
768
|
+
return acc;
|
|
769
|
+
}
|
|
606
770
|
sorted(comparator) {
|
|
607
771
|
const decorated = [...this.entries()].map((entry, index) => ({
|
|
608
772
|
entry,
|
|
@@ -613,22 +777,34 @@ class Collection extends Map {
|
|
|
613
777
|
const comparison = comparator(x.entry[1], y.entry[1], x.entry[0], y.entry[0]);
|
|
614
778
|
return comparison !== 0 ? comparison : x.index - y.index;
|
|
615
779
|
});
|
|
616
|
-
const result =
|
|
780
|
+
const result = this.#derived();
|
|
617
781
|
for (const { entry } of decorated)
|
|
618
782
|
result.set(entry[0], entry[1]);
|
|
619
783
|
return result;
|
|
620
784
|
}
|
|
621
|
-
random() {
|
|
622
|
-
|
|
623
|
-
|
|
785
|
+
random(amount) {
|
|
786
|
+
if (amount !== undefined)
|
|
787
|
+
return sample([...this.values()], amount);
|
|
788
|
+
const size = this.size;
|
|
789
|
+
if (size === 0)
|
|
624
790
|
return;
|
|
625
|
-
|
|
791
|
+
let index = Math.floor(Math.random() * size);
|
|
792
|
+
for (const value of this.values())
|
|
793
|
+
if (index-- === 0)
|
|
794
|
+
return value;
|
|
795
|
+
return;
|
|
626
796
|
}
|
|
627
|
-
randomKey() {
|
|
628
|
-
|
|
629
|
-
|
|
797
|
+
randomKey(amount) {
|
|
798
|
+
if (amount !== undefined)
|
|
799
|
+
return sample([...this.keys()], amount);
|
|
800
|
+
const size = this.size;
|
|
801
|
+
if (size === 0)
|
|
630
802
|
return;
|
|
631
|
-
|
|
803
|
+
let index = Math.floor(Math.random() * size);
|
|
804
|
+
for (const key of this.keys())
|
|
805
|
+
if (index-- === 0)
|
|
806
|
+
return key;
|
|
807
|
+
return;
|
|
632
808
|
}
|
|
633
809
|
at(index) {
|
|
634
810
|
const arr = [...this.values()];
|
|
@@ -649,4 +825,4 @@ export {
|
|
|
649
825
|
Collection
|
|
650
826
|
};
|
|
651
827
|
|
|
652
|
-
//# debugId=
|
|
828
|
+
//# debugId=72EF4AA34379CD3464756E2164756E21
|