@oscarpalmer/atoms 0.189.0 → 0.190.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/dist/beacon.d.mts +51 -31
- package/dist/beacon.mjs +163 -141
- package/dist/color/index.d.mts +1 -2
- package/dist/color/index.mjs +2 -2
- package/dist/color/instance.d.mts +3 -167
- package/dist/color/instance.mjs +58 -217
- package/dist/color/misc/get.d.mts +1 -2
- package/dist/color/misc/get.mjs +3 -3
- package/dist/color/misc/index.d.mts +4 -4
- package/dist/color/misc/index.mjs +9 -9
- package/dist/color/misc/is.d.mts +1 -2
- package/dist/color/misc/is.mjs +5 -2
- package/dist/color/models.d.mts +158 -2
- package/dist/function/memoize.d.mts +3 -9
- package/dist/function/memoize.mjs +43 -90
- package/dist/function/once.mjs +16 -4
- package/dist/herald.d.mts +19 -15
- package/dist/herald.mjs +79 -89
- package/dist/index.d.mts +173 -162
- package/dist/index.mjs +754 -996
- package/dist/internal/result.d.mts +6 -6
- package/dist/internal/result.mjs +1 -1
- package/dist/internal/value/has.d.mts +2 -2
- package/dist/logger.d.mts +7 -7
- package/dist/logger.mjs +72 -51
- package/dist/promise/helpers.d.mts +2 -2
- package/dist/promise/helpers.mjs +2 -2
- package/dist/queue.d.mts +24 -12
- package/dist/queue.mjs +288 -346
- package/dist/string/fuzzy.d.mts +4 -13
- package/dist/string/fuzzy.mjs +15 -41
- package/package.json +2 -2
- package/src/beacon.ts +262 -160
- package/src/color/index.ts +8 -8
- package/src/color/instance.ts +82 -258
- package/src/color/misc/get.ts +4 -4
- package/src/color/misc/index.ts +10 -11
- package/src/color/misc/is.ts +4 -1
- package/src/color/models.ts +180 -2
- package/src/function/memoize.ts +74 -65
- package/src/function/once.ts +4 -0
- package/src/herald.ts +136 -94
- package/src/internal/result.ts +6 -6
- package/src/internal/value/has.ts +2 -2
- package/src/logger.ts +93 -42
- package/src/promise/helpers.ts +2 -2
- package/src/queue.ts +480 -375
- package/src/string/fuzzy.ts +36 -31
package/dist/queue.mjs
CHANGED
|
@@ -1,345 +1,6 @@
|
|
|
1
1
|
import { getNumberOrDefault } from "./internal/number.mjs";
|
|
2
2
|
//#region src/queue.ts
|
|
3
3
|
/**
|
|
4
|
-
* A queue that can be used to manage (a)synchronous tasks with a specific key
|
|
5
|
-
*/
|
|
6
|
-
var KeyedQueue = class {
|
|
7
|
-
#callback;
|
|
8
|
-
#options;
|
|
9
|
-
#queues = /* @__PURE__ */ new Map();
|
|
10
|
-
/**
|
|
11
|
-
* Get keys of all active queues
|
|
12
|
-
*/
|
|
13
|
-
get active() {
|
|
14
|
-
return this.#getStatus(STATUS_ACTIVE);
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Does the queue automatically start when the first item is added?
|
|
18
|
-
*/
|
|
19
|
-
get autostart() {
|
|
20
|
-
return this.#options.autostart;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Maximum number of runners to process the queue concurrently
|
|
24
|
-
*/
|
|
25
|
-
get concurrency() {
|
|
26
|
-
return this.#options.concurrency;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Get keys of all empty queues
|
|
30
|
-
*/
|
|
31
|
-
get empty() {
|
|
32
|
-
return this.#getStatus(STATUS_EMPTY);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Get keys of all full queues
|
|
36
|
-
*/
|
|
37
|
-
get full() {
|
|
38
|
-
return this.#getStatus(STATUS_FULL);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Number of items in all queues
|
|
42
|
-
*/
|
|
43
|
-
get items() {
|
|
44
|
-
const size = {};
|
|
45
|
-
const queues = this.#queues.entries();
|
|
46
|
-
for (const [key, queue] of queues) size[key] = queue.size;
|
|
47
|
-
return size;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Keys of all queues
|
|
51
|
-
*/
|
|
52
|
-
get keys() {
|
|
53
|
-
return [...this.#queues.keys()];
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Maximum number of items allowed in the queue
|
|
57
|
-
*/
|
|
58
|
-
get maximum() {
|
|
59
|
-
return this.#options.maximum;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Are all queues paused?
|
|
63
|
-
*/
|
|
64
|
-
get paused() {
|
|
65
|
-
return this.#getStatus(STATUS_PAUSED);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Number of queues
|
|
69
|
-
*/
|
|
70
|
-
get queues() {
|
|
71
|
-
return this.#queues.size;
|
|
72
|
-
}
|
|
73
|
-
constructor(callback, options) {
|
|
74
|
-
this.#callback = callback;
|
|
75
|
-
this.#options = options;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Queue an item for a specific key
|
|
79
|
-
*
|
|
80
|
-
* @param key Key to queue the item for
|
|
81
|
-
* @param parameters Parameters to use when item runs
|
|
82
|
-
* @param signal Optional signal to abort the item
|
|
83
|
-
* @returns Queued item
|
|
84
|
-
*/
|
|
85
|
-
add(key, parameters, signal) {
|
|
86
|
-
return this.#getQueue(key, true).add(parameters, signal);
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Clear all items for a specific key _(or all items for all keys, if no key is provided)_
|
|
90
|
-
*
|
|
91
|
-
* @param key Optional key to clear the queue for
|
|
92
|
-
*/
|
|
93
|
-
clear(key) {
|
|
94
|
-
this.#handleQueues(HANDLE_CLEAR, key);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Get the queue for a specific key
|
|
98
|
-
*
|
|
99
|
-
* @param key Key to get the queue for
|
|
100
|
-
* @returns Queue for the key, or `undefined` if it doesn't exist
|
|
101
|
-
*/
|
|
102
|
-
get(key) {
|
|
103
|
-
return this.#getQueue(key);
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Pause the queue for a specific key _(or all queues, if no key is provided)_
|
|
107
|
-
*
|
|
108
|
-
* @param key Optional key to pause the queue for
|
|
109
|
-
*/
|
|
110
|
-
pause(key) {
|
|
111
|
-
this.#handleQueues(HANDLE_PAUSE, key);
|
|
112
|
-
}
|
|
113
|
-
remove(key, id) {
|
|
114
|
-
if (key == null) {
|
|
115
|
-
this.#handleQueues(HANDLE_CLEAR);
|
|
116
|
-
this.#queues.clear();
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const queue = this.#getQueue(key);
|
|
120
|
-
if (queue == null) return;
|
|
121
|
-
if (typeof id === "number") {
|
|
122
|
-
queue.remove(id);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
queue.clear();
|
|
126
|
-
this.#queues.delete(key);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Resume the queue for a specific key _(or all queues, if no key is provided)_
|
|
130
|
-
*
|
|
131
|
-
* @param key Optional key to resume the queue for
|
|
132
|
-
*/
|
|
133
|
-
resume(key) {
|
|
134
|
-
this.#handleQueues(HANDLE_RESUME, key);
|
|
135
|
-
}
|
|
136
|
-
#getQueue(key, add) {
|
|
137
|
-
if (typeof key !== "string" || key.trim().length === 0) throw new TypeError(MESSAGE_KEY);
|
|
138
|
-
let queue = this.#queues.get(key);
|
|
139
|
-
if (queue == null && add === true) {
|
|
140
|
-
queue = new Queue(this.#callback, this.#options, key);
|
|
141
|
-
this.#queues.set(key, queue);
|
|
142
|
-
}
|
|
143
|
-
return queue;
|
|
144
|
-
}
|
|
145
|
-
#getStatus(status) {
|
|
146
|
-
const queues = this.#queues.entries();
|
|
147
|
-
const result = [];
|
|
148
|
-
for (const [key, queue] of queues) if (queue[status]) result.push(key);
|
|
149
|
-
return result;
|
|
150
|
-
}
|
|
151
|
-
#handleQueues(type, key) {
|
|
152
|
-
if (typeof key === "string") {
|
|
153
|
-
this.#getQueue(key)?.[type]();
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
const queues = this.#queues.values();
|
|
157
|
-
for (const queue of queues) queue[type]();
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
/**
|
|
161
|
-
* A queue that can be used to manage (a)synchronous tasks
|
|
162
|
-
*/
|
|
163
|
-
var Queue = class {
|
|
164
|
-
#callback;
|
|
165
|
-
#handled = [];
|
|
166
|
-
#id = 0;
|
|
167
|
-
#items = [];
|
|
168
|
-
#key;
|
|
169
|
-
#options;
|
|
170
|
-
#paused;
|
|
171
|
-
#runners = 0;
|
|
172
|
-
/**
|
|
173
|
-
* Is the queue active?
|
|
174
|
-
*/
|
|
175
|
-
get active() {
|
|
176
|
-
return this.#runners > 0;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Does the queue automatically start when the first item is added?
|
|
180
|
-
*/
|
|
181
|
-
get autostart() {
|
|
182
|
-
return this.#options.autostart;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Maximum number of runners to process the queue concurrently
|
|
186
|
-
*/
|
|
187
|
-
get concurrency() {
|
|
188
|
-
return this.#options.concurrency;
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Is the queue empty?
|
|
192
|
-
*/
|
|
193
|
-
get empty() {
|
|
194
|
-
return this.#items.length === 0;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Is the queue full?
|
|
198
|
-
*/
|
|
199
|
-
get full() {
|
|
200
|
-
return this.#options.maximum > 0 && this.#items.length >= this.#options.maximum;
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Maximum number of items allowed in the queue
|
|
204
|
-
*/
|
|
205
|
-
get maximum() {
|
|
206
|
-
return this.#options.maximum;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Is the queue paused?
|
|
210
|
-
*/
|
|
211
|
-
get paused() {
|
|
212
|
-
return this.#paused;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Number of items in the queue
|
|
216
|
-
*/
|
|
217
|
-
get size() {
|
|
218
|
-
return this.#items.length;
|
|
219
|
-
}
|
|
220
|
-
constructor(callback, options, key) {
|
|
221
|
-
this.#callback = callback;
|
|
222
|
-
this.#key = key;
|
|
223
|
-
this.#options = options;
|
|
224
|
-
this.#paused = !options.autostart;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Add an item to the queue
|
|
228
|
-
*
|
|
229
|
-
* @param parameters Parameters to use when item runs
|
|
230
|
-
* @param signal Optional signal to abort the item
|
|
231
|
-
* @returns Queued item
|
|
232
|
-
*/
|
|
233
|
-
add(parameters, signal) {
|
|
234
|
-
if (this.full) throw new QueueError(MESSAGE_MAXIMUM);
|
|
235
|
-
const abortSignal = signal instanceof AbortSignal ? signal : void 0;
|
|
236
|
-
if (abortSignal?.aborted ?? false) throw new Error(abortSignal.reason);
|
|
237
|
-
const id = this.#identify();
|
|
238
|
-
let rejector;
|
|
239
|
-
let resolver;
|
|
240
|
-
const promise = new Promise((resolve, reject) => {
|
|
241
|
-
rejector = reject;
|
|
242
|
-
resolver = resolve;
|
|
243
|
-
});
|
|
244
|
-
const aborter = abortSignal == null ? void 0 : () => rejector(abortSignal.reason);
|
|
245
|
-
signal?.addEventListener(EVENT_NAME, aborter, EVENT_OPTIONS);
|
|
246
|
-
this.#items.push({
|
|
247
|
-
id,
|
|
248
|
-
parameters,
|
|
249
|
-
promise,
|
|
250
|
-
abort: aborter,
|
|
251
|
-
key: this.#key,
|
|
252
|
-
reject: rejector,
|
|
253
|
-
resolve: resolver,
|
|
254
|
-
signal: abortSignal
|
|
255
|
-
});
|
|
256
|
-
if (this.#options.autostart) this.#run();
|
|
257
|
-
return {
|
|
258
|
-
id,
|
|
259
|
-
promise
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Remove and reject all items in the queue
|
|
264
|
-
*/
|
|
265
|
-
clear() {
|
|
266
|
-
const items = this.#items.splice(0);
|
|
267
|
-
const { length } = items;
|
|
268
|
-
for (let index = 0; index < length; index += 1) {
|
|
269
|
-
const { abort, reject, signal } = items[index];
|
|
270
|
-
reject(new QueueError(MESSAGE_CLEAR));
|
|
271
|
-
signal?.removeEventListener(EVENT_NAME, abort);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Pause the queue
|
|
276
|
-
*
|
|
277
|
-
* - Currently running items will not be stopped
|
|
278
|
-
* - New added items will not run until the queue is resumed
|
|
279
|
-
*/
|
|
280
|
-
pause() {
|
|
281
|
-
this.#paused = true;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Remove and reject a specific item in the queue
|
|
285
|
-
*
|
|
286
|
-
* @param id ID of queued item
|
|
287
|
-
*/
|
|
288
|
-
remove(id) {
|
|
289
|
-
const index = this.#items.findIndex((item) => item.id === id);
|
|
290
|
-
if (index > -1) {
|
|
291
|
-
const { abort, reject, signal } = this.#items.splice(index, 1)[0];
|
|
292
|
-
reject(new QueueError(MESSAGE_REMOVE));
|
|
293
|
-
signal?.removeEventListener(EVENT_NAME, abort);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Resume the queue
|
|
298
|
-
*/
|
|
299
|
-
resume() {
|
|
300
|
-
if (this.#paused) {
|
|
301
|
-
const handled = this.#handled.splice(0);
|
|
302
|
-
const { length } = handled;
|
|
303
|
-
for (let index = 0; index < length; index += 1) handled[index]();
|
|
304
|
-
}
|
|
305
|
-
this.#paused = false;
|
|
306
|
-
const length = Math.min(this.#options.concurrency, this.#items.length);
|
|
307
|
-
for (let index = 0; index < length; index += 1) this.#run();
|
|
308
|
-
}
|
|
309
|
-
#identify() {
|
|
310
|
-
this.#id += 1;
|
|
311
|
-
return this.#id;
|
|
312
|
-
}
|
|
313
|
-
async #run() {
|
|
314
|
-
if (this.#paused || this.#runners >= this.#options.concurrency) return;
|
|
315
|
-
this.#runners += 1;
|
|
316
|
-
let item = this.#items.shift();
|
|
317
|
-
while (item != null) {
|
|
318
|
-
let error = false;
|
|
319
|
-
let result;
|
|
320
|
-
try {
|
|
321
|
-
if (!(item.signal?.aborted ?? false)) {
|
|
322
|
-
const parameters = item.key == null ? item.parameters : [item.key, ...item.parameters];
|
|
323
|
-
result = await this.#callback(...parameters);
|
|
324
|
-
}
|
|
325
|
-
} catch (thrown) {
|
|
326
|
-
error = true;
|
|
327
|
-
result = thrown;
|
|
328
|
-
}
|
|
329
|
-
if (this.#paused) {
|
|
330
|
-
const paused = item;
|
|
331
|
-
this.#handled.push(() => {
|
|
332
|
-
handleQueuedResult(paused, error, result, this.#items.length === 0);
|
|
333
|
-
});
|
|
334
|
-
break;
|
|
335
|
-
}
|
|
336
|
-
handleQueuedResult(item, error, result, this.#items.length === 0);
|
|
337
|
-
item = this.#items.shift();
|
|
338
|
-
}
|
|
339
|
-
this.#runners -= 1;
|
|
340
|
-
}
|
|
341
|
-
};
|
|
342
|
-
/**
|
|
343
4
|
* An error thrown by the Queue when an operation fails
|
|
344
5
|
*/
|
|
345
6
|
var QueueError = class extends Error {
|
|
@@ -348,6 +9,119 @@ var QueueError = class extends Error {
|
|
|
348
9
|
this.name = ERROR_NAME;
|
|
349
10
|
}
|
|
350
11
|
};
|
|
12
|
+
function createQueue(callback, options, key) {
|
|
13
|
+
if (typeof callback !== "function") throw new TypeError(MESSAGE_CALLBACK);
|
|
14
|
+
const state = {
|
|
15
|
+
callback,
|
|
16
|
+
key,
|
|
17
|
+
handled: [],
|
|
18
|
+
id: 0,
|
|
19
|
+
items: [],
|
|
20
|
+
options: getOptions(options),
|
|
21
|
+
paused: !getBooleanOrDefault(options?.autostart, true),
|
|
22
|
+
runners: 0
|
|
23
|
+
};
|
|
24
|
+
const instance = {
|
|
25
|
+
add: (parameters, signal) => {
|
|
26
|
+
if (instance.full) throw new QueueError(MESSAGE_MAXIMUM);
|
|
27
|
+
const abortSignal = signal instanceof AbortSignal ? signal : void 0;
|
|
28
|
+
if (abortSignal?.aborted ?? false) throw new Error(abortSignal.reason);
|
|
29
|
+
const id = identify(state);
|
|
30
|
+
let rejector;
|
|
31
|
+
let resolver;
|
|
32
|
+
const promise = new Promise((resolve, reject) => {
|
|
33
|
+
rejector = reject;
|
|
34
|
+
resolver = resolve;
|
|
35
|
+
});
|
|
36
|
+
const aborter = abortSignal == null ? void 0 : () => rejector(abortSignal.reason);
|
|
37
|
+
signal?.addEventListener(EVENT_NAME, aborter, EVENT_OPTIONS);
|
|
38
|
+
state.items.push({
|
|
39
|
+
id,
|
|
40
|
+
parameters,
|
|
41
|
+
promise,
|
|
42
|
+
abort: aborter,
|
|
43
|
+
key: state.key,
|
|
44
|
+
reject: rejector,
|
|
45
|
+
resolve: resolver,
|
|
46
|
+
signal: abortSignal
|
|
47
|
+
});
|
|
48
|
+
if (state.options.autostart) run(state);
|
|
49
|
+
return {
|
|
50
|
+
id,
|
|
51
|
+
promise
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
clear: () => {
|
|
55
|
+
const items = state.items.splice(0);
|
|
56
|
+
const { length } = items;
|
|
57
|
+
for (let index = 0; index < length; index += 1) {
|
|
58
|
+
const { abort, reject, signal } = items[index];
|
|
59
|
+
reject(new QueueError(MESSAGE_CLEAR));
|
|
60
|
+
signal?.removeEventListener(EVENT_NAME, abort);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
pause: () => {
|
|
64
|
+
state.paused = true;
|
|
65
|
+
},
|
|
66
|
+
remove: (id) => {
|
|
67
|
+
const index = state.items.findIndex((item) => item.id === id);
|
|
68
|
+
if (index > -1) {
|
|
69
|
+
const { abort, reject, signal } = state.items.splice(index, 1)[0];
|
|
70
|
+
reject(new QueueError(MESSAGE_REMOVE));
|
|
71
|
+
signal?.removeEventListener(EVENT_NAME, abort);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
resume: () => {
|
|
75
|
+
if (state.paused) {
|
|
76
|
+
const handled = state.handled.splice(0);
|
|
77
|
+
const { length } = handled;
|
|
78
|
+
for (let index = 0; index < length; index += 1) handled[index]();
|
|
79
|
+
}
|
|
80
|
+
state.paused = false;
|
|
81
|
+
const length = Math.min(state.options.concurrency, state.items.length);
|
|
82
|
+
for (let index = 0; index < length; index += 1) run(state);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
Object.defineProperties(instance, {
|
|
86
|
+
[KEY_QUEUE]: {
|
|
87
|
+
enumerable: false,
|
|
88
|
+
value: NAME_QUEUE
|
|
89
|
+
},
|
|
90
|
+
active: {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: () => state.runners > 0
|
|
93
|
+
},
|
|
94
|
+
autostart: {
|
|
95
|
+
enumerable: true,
|
|
96
|
+
get: () => state.options.autostart
|
|
97
|
+
},
|
|
98
|
+
concurrency: {
|
|
99
|
+
enumerable: true,
|
|
100
|
+
get: () => state.options.concurrency
|
|
101
|
+
},
|
|
102
|
+
empty: {
|
|
103
|
+
enumerable: true,
|
|
104
|
+
get: () => state.items.length === 0
|
|
105
|
+
},
|
|
106
|
+
full: {
|
|
107
|
+
enumerable: true,
|
|
108
|
+
get: () => state.options.maximum > 0 && state.items.length >= state.options.maximum
|
|
109
|
+
},
|
|
110
|
+
maximum: {
|
|
111
|
+
enumerable: true,
|
|
112
|
+
get: () => state.options.maximum
|
|
113
|
+
},
|
|
114
|
+
paused: {
|
|
115
|
+
enumerable: true,
|
|
116
|
+
get: () => state.paused
|
|
117
|
+
},
|
|
118
|
+
size: {
|
|
119
|
+
enumerable: true,
|
|
120
|
+
get: () => state.items.length
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return Object.freeze(instance);
|
|
124
|
+
}
|
|
351
125
|
function getBooleanOrDefault(value, defaultValue) {
|
|
352
126
|
return typeof value === "boolean" ? value : defaultValue;
|
|
353
127
|
}
|
|
@@ -359,27 +133,193 @@ function getOptions(input) {
|
|
|
359
133
|
maximum: getNumberOrDefault(options.maximum, 0)
|
|
360
134
|
};
|
|
361
135
|
}
|
|
136
|
+
function getQueue(state, key, add) {
|
|
137
|
+
if (typeof key !== "string" || key.trim().length === 0) throw new TypeError(MESSAGE_KEY);
|
|
138
|
+
let queue = state.queues.get(key);
|
|
139
|
+
if (queue == null && add === true) {
|
|
140
|
+
queue = createQueue(state.callback, state.options, key);
|
|
141
|
+
state.queues.set(key, queue);
|
|
142
|
+
}
|
|
143
|
+
return queue;
|
|
144
|
+
}
|
|
145
|
+
function getStatus(state, status) {
|
|
146
|
+
const queues = state.queues.entries();
|
|
147
|
+
const result = [];
|
|
148
|
+
for (const [key, queue] of queues) if (queue[status]) result.push(key);
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
362
151
|
function handleQueuedResult(item, error, result, finished) {
|
|
363
152
|
item.signal?.removeEventListener(EVENT_NAME, item.abort);
|
|
364
|
-
if (item.signal?.aborted ?? false)
|
|
365
|
-
|
|
366
|
-
|
|
153
|
+
if (item.signal?.aborted ?? false) {
|
|
154
|
+
item.reject();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (error) {
|
|
158
|
+
item.reject(result);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
item.resolve({
|
|
367
162
|
finished,
|
|
368
163
|
value: result
|
|
369
164
|
});
|
|
370
165
|
}
|
|
166
|
+
function handleQueues(state, type, key) {
|
|
167
|
+
if (typeof key === "string") {
|
|
168
|
+
getQueue(state, key)?.[type]();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const queues = state.queues.values();
|
|
172
|
+
for (const queue of queues) queue[type]();
|
|
173
|
+
}
|
|
174
|
+
function identify(state) {
|
|
175
|
+
state.id += 1;
|
|
176
|
+
return state.id;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Is the value keyed queue?
|
|
180
|
+
*
|
|
181
|
+
* @param value Value to check
|
|
182
|
+
* @returns `true` if the value is a keyed queue, otherwise `false`
|
|
183
|
+
*/
|
|
184
|
+
function isKeyedQueue(value) {
|
|
185
|
+
return isQueueInstance(NAME_KEYED, value);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Is the value a queue?
|
|
189
|
+
*
|
|
190
|
+
* @param value Value to check
|
|
191
|
+
* @returns `true` if the value is a queue, otherwise `false`
|
|
192
|
+
*/
|
|
193
|
+
function isQueue(value) {
|
|
194
|
+
return isQueueInstance(NAME_QUEUE, value);
|
|
195
|
+
}
|
|
196
|
+
function isQueueInstance(name, value) {
|
|
197
|
+
return typeof value === "object" && value != null && value[KEY_QUEUE] === name;
|
|
198
|
+
}
|
|
371
199
|
function keyedQueue(callback, options) {
|
|
372
200
|
if (typeof callback !== "function") throw new TypeError(MESSAGE_CALLBACK);
|
|
373
|
-
|
|
201
|
+
const state = {
|
|
202
|
+
callback,
|
|
203
|
+
options: getOptions(options),
|
|
204
|
+
queues: /* @__PURE__ */ new Map()
|
|
205
|
+
};
|
|
206
|
+
const instance = {
|
|
207
|
+
add: (key, parameters, signal) => getQueue(state, key, true).add(parameters, signal),
|
|
208
|
+
clear: (key) => {
|
|
209
|
+
handleQueues(state, HANDLE_CLEAR, key);
|
|
210
|
+
},
|
|
211
|
+
get: (key) => getQueue(state, key),
|
|
212
|
+
pause: (key) => {
|
|
213
|
+
handleQueues(state, HANDLE_PAUSE, key);
|
|
214
|
+
},
|
|
215
|
+
remove: (key, id) => {
|
|
216
|
+
if (key == null) {
|
|
217
|
+
handleQueues(state, HANDLE_CLEAR);
|
|
218
|
+
state.queues.clear();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const queue = getQueue(state, key);
|
|
222
|
+
if (queue == null) return;
|
|
223
|
+
if (typeof id === "number") {
|
|
224
|
+
queue.remove(id);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
queue.clear();
|
|
228
|
+
state.queues.delete(key);
|
|
229
|
+
},
|
|
230
|
+
resume: (key) => {
|
|
231
|
+
handleQueues(state, HANDLE_RESUME, key);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
Object.defineProperties(instance, {
|
|
235
|
+
[KEY_QUEUE]: {
|
|
236
|
+
enumerable: false,
|
|
237
|
+
value: NAME_KEYED
|
|
238
|
+
},
|
|
239
|
+
active: {
|
|
240
|
+
enumerable: true,
|
|
241
|
+
get: () => getStatus(state, STATUS_ACTIVE)
|
|
242
|
+
},
|
|
243
|
+
autostart: {
|
|
244
|
+
enumerable: true,
|
|
245
|
+
get: () => state.options.autostart
|
|
246
|
+
},
|
|
247
|
+
concurrency: {
|
|
248
|
+
enumerable: true,
|
|
249
|
+
get: () => state.options.concurrency
|
|
250
|
+
},
|
|
251
|
+
empty: {
|
|
252
|
+
enumerable: true,
|
|
253
|
+
get: () => getStatus(state, STATUS_EMPTY)
|
|
254
|
+
},
|
|
255
|
+
full: {
|
|
256
|
+
enumerable: true,
|
|
257
|
+
get: () => getStatus(state, STATUS_FULL)
|
|
258
|
+
},
|
|
259
|
+
items: {
|
|
260
|
+
enumerable: true,
|
|
261
|
+
get: () => {
|
|
262
|
+
const size = {};
|
|
263
|
+
const queues = state.queues.entries();
|
|
264
|
+
for (const [key, queue] of queues) size[key] = queue.size;
|
|
265
|
+
return size;
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
keys: {
|
|
269
|
+
enumerable: true,
|
|
270
|
+
get: () => [...state.queues.keys()]
|
|
271
|
+
},
|
|
272
|
+
maximum: {
|
|
273
|
+
enumerable: true,
|
|
274
|
+
get: () => state.options.maximum
|
|
275
|
+
},
|
|
276
|
+
paused: {
|
|
277
|
+
enumerable: true,
|
|
278
|
+
get: () => getStatus(state, STATUS_PAUSED)
|
|
279
|
+
},
|
|
280
|
+
queues: {
|
|
281
|
+
enumerable: true,
|
|
282
|
+
get: () => state.queues.size
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
return Object.freeze(instance);
|
|
374
286
|
}
|
|
375
287
|
function queue(callback, options) {
|
|
376
|
-
|
|
377
|
-
return new Queue(callback, getOptions(options));
|
|
288
|
+
return createQueue(callback, options);
|
|
378
289
|
}
|
|
379
290
|
queue.keyed = keyedQueue;
|
|
291
|
+
async function run(state) {
|
|
292
|
+
if (state.paused || state.runners >= state.options.concurrency) return;
|
|
293
|
+
state.runners += 1;
|
|
294
|
+
let item = state.items.shift();
|
|
295
|
+
while (item != null) {
|
|
296
|
+
let error = false;
|
|
297
|
+
let result;
|
|
298
|
+
try {
|
|
299
|
+
if (!(item.signal?.aborted ?? false)) {
|
|
300
|
+
const parameters = item.key == null ? item.parameters : [item.key, ...item.parameters];
|
|
301
|
+
result = await state.callback(...parameters);
|
|
302
|
+
}
|
|
303
|
+
} catch (thrown) {
|
|
304
|
+
error = true;
|
|
305
|
+
result = thrown;
|
|
306
|
+
}
|
|
307
|
+
if (state.paused) {
|
|
308
|
+
const paused = item;
|
|
309
|
+
state.handled.push(() => {
|
|
310
|
+
handleQueuedResult(paused, error, result, state.items.length === 0);
|
|
311
|
+
});
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
handleQueuedResult(item, error, result, state.items.length === 0);
|
|
315
|
+
item = state.items.shift();
|
|
316
|
+
}
|
|
317
|
+
state.runners -= 1;
|
|
318
|
+
}
|
|
380
319
|
const ERROR_NAME = "QueueError";
|
|
381
320
|
const EVENT_NAME = "abort";
|
|
382
321
|
const EVENT_OPTIONS = { once: true };
|
|
322
|
+
const KEY_QUEUE = "$queue";
|
|
383
323
|
const HANDLE_CLEAR = "clear";
|
|
384
324
|
const HANDLE_PAUSE = "pause";
|
|
385
325
|
const HANDLE_RESUME = "resume";
|
|
@@ -388,9 +328,11 @@ const MESSAGE_CLEAR = "Queue was cleared";
|
|
|
388
328
|
const MESSAGE_KEY = "Key must be a non-empty string";
|
|
389
329
|
const MESSAGE_MAXIMUM = "Queue has reached its maximum size";
|
|
390
330
|
const MESSAGE_REMOVE = "Item removed from queue";
|
|
331
|
+
const NAME_KEYED = "keyedQueue";
|
|
332
|
+
const NAME_QUEUE = "queue";
|
|
391
333
|
const STATUS_ACTIVE = "active";
|
|
392
334
|
const STATUS_EMPTY = "empty";
|
|
393
335
|
const STATUS_FULL = "full";
|
|
394
336
|
const STATUS_PAUSED = "paused";
|
|
395
337
|
//#endregion
|
|
396
|
-
export { keyedQueue, queue };
|
|
338
|
+
export { QueueError, isKeyedQueue, isQueue, isQueueInstance, keyedQueue, queue };
|
package/dist/string/fuzzy.d.mts
CHANGED
|
@@ -3,8 +3,7 @@ import { PlainObject } from "../models.mjs";
|
|
|
3
3
|
/**
|
|
4
4
|
* Fuzzy searcher for an array of items
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
#private;
|
|
6
|
+
type Fuzzy<Item> = {
|
|
8
7
|
/**
|
|
9
8
|
* Get items currently being searched through
|
|
10
9
|
*
|
|
@@ -23,7 +22,6 @@ declare class Fuzzy<Item> {
|
|
|
23
22
|
* @returns Stringified items
|
|
24
23
|
*/
|
|
25
24
|
get strings(): string[];
|
|
26
|
-
constructor(state: FuzzyState<Item>);
|
|
27
25
|
/**
|
|
28
26
|
* Search for items matching the given value
|
|
29
27
|
*
|
|
@@ -40,7 +38,7 @@ declare class Fuzzy<Item> {
|
|
|
40
38
|
* @returns Search results, with exact matches _(ordered)_ and similar matches _(ordered by relevance)_
|
|
41
39
|
*/
|
|
42
40
|
search(value: string, limit: number): FuzzyResult<Item>;
|
|
43
|
-
}
|
|
41
|
+
};
|
|
44
42
|
type FuzzyConfiguration<Item> = {
|
|
45
43
|
/**
|
|
46
44
|
* Handler to stringify items
|
|
@@ -87,13 +85,6 @@ type FuzzyResult<Item> = {
|
|
|
87
85
|
* Options for fuzzy searching
|
|
88
86
|
*/
|
|
89
87
|
type FuzzySearchOptions = FuzzyOptions;
|
|
90
|
-
type FuzzyState<Item> = {
|
|
91
|
-
handler: (item: Item) => string;
|
|
92
|
-
items: Item[];
|
|
93
|
-
limit?: number;
|
|
94
|
-
strings: string[];
|
|
95
|
-
tolerance: number;
|
|
96
|
-
};
|
|
97
88
|
/**
|
|
98
89
|
* Create a fuzzy searcher for an array of items
|
|
99
90
|
*
|
|
@@ -126,8 +117,8 @@ declare namespace fuzzy {
|
|
|
126
117
|
*
|
|
127
118
|
* @param haystack Haystack to search through
|
|
128
119
|
* @param needle Needle to search for
|
|
129
|
-
* @returns `true` if the needle matches the haystack in a fuzzy way, `false`
|
|
120
|
+
* @returns `true` if the needle matches the haystack in a fuzzy way, otherwise `false`
|
|
130
121
|
*/
|
|
131
122
|
declare function fuzzyMatch(haystack: string, needle: string): boolean;
|
|
132
123
|
//#endregion
|
|
133
|
-
export { FuzzyConfiguration, FuzzyOptions, FuzzyResult, FuzzySearchOptions, fuzzy, fuzzyMatch };
|
|
124
|
+
export { Fuzzy, FuzzyConfiguration, FuzzyOptions, FuzzyResult, FuzzySearchOptions, fuzzy, fuzzyMatch };
|