@oscarpalmer/atoms 0.193.0 → 0.194.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.
Files changed (204) hide show
  1. package/dist/array/difference.mjs +2 -2
  2. package/dist/array/intersection.mjs +2 -2
  3. package/dist/array/match.mjs +13 -13
  4. package/dist/array/slice.mjs +5 -5
  5. package/dist/array/sort.d.mts +5 -1
  6. package/dist/array/sort.mjs +4 -2
  7. package/dist/array/union.mjs +2 -2
  8. package/dist/beacon.d.mts +8 -1
  9. package/dist/beacon.mjs +52 -60
  10. package/dist/color/constants.d.mts +1 -1
  11. package/dist/color/constants.mjs +3 -5
  12. package/dist/color/instance.mjs +34 -41
  13. package/dist/color/misc/format.d.mts +3 -2
  14. package/dist/color/misc/format.mjs +4 -1
  15. package/dist/color/misc/is.d.mts +9 -1
  16. package/dist/color/misc/is.mjs +11 -1
  17. package/dist/color/misc/state.d.mts +6 -6
  18. package/dist/color/misc/state.mjs +11 -14
  19. package/dist/color/models.d.mts +23 -68
  20. package/dist/function/assert.mjs +2 -2
  21. package/dist/function/limit.d.mts +0 -6
  22. package/dist/function/limit.mjs +2 -2
  23. package/dist/function/memoize.mjs +19 -32
  24. package/dist/function/once.d.mts +0 -3
  25. package/dist/function/once.mjs +16 -13
  26. package/dist/function/retry.d.mts +1 -24
  27. package/dist/function/retry.mjs +1 -1
  28. package/dist/function/work.mjs +13 -11
  29. package/dist/herald.d.mts +30 -31
  30. package/dist/herald.mjs +74 -56
  31. package/dist/index.d.mts +100 -185
  32. package/dist/index.mjs +680 -702
  33. package/dist/internal/abort.d.mts +10 -0
  34. package/dist/internal/abort.mjs +14 -0
  35. package/dist/internal/array/chunk.mjs +2 -2
  36. package/dist/internal/array/find.mjs +2 -2
  37. package/dist/internal/array/sets.d.mts +4 -4
  38. package/dist/internal/array/sets.mjs +7 -7
  39. package/dist/internal/function/timer.mjs +19 -15
  40. package/dist/internal/number.mjs +7 -7
  41. package/dist/internal/result.mjs +3 -3
  42. package/dist/internal/sized.mjs +4 -4
  43. package/dist/internal/string.mjs +4 -4
  44. package/dist/internal/subscription.d.mts +24 -8
  45. package/dist/internal/subscription.mjs +49 -36
  46. package/dist/internal/value/equal.mjs +6 -6
  47. package/dist/internal/value/misc.mjs +14 -14
  48. package/dist/internal/value/set.mjs +2 -2
  49. package/dist/logger.mjs +15 -39
  50. package/dist/promise/constants.d.mts +17 -0
  51. package/dist/promise/constants.mjs +14 -0
  52. package/dist/promise/delay.mjs +7 -10
  53. package/dist/promise/helpers.mjs +1 -1
  54. package/dist/promise/index.mjs +14 -17
  55. package/dist/promise/misc.d.mts +2 -1
  56. package/dist/promise/misc.mjs +8 -7
  57. package/dist/promise/models.d.mts +4 -16
  58. package/dist/promise/models.mjs +4 -13
  59. package/dist/promise/timed.mjs +9 -10
  60. package/dist/query.mjs +15 -15
  61. package/dist/queue.mjs +103 -116
  62. package/dist/random.mjs +7 -7
  63. package/dist/result/index.d.mts +0 -3
  64. package/dist/result/index.mjs +1 -1
  65. package/dist/result/match.d.mts +0 -3
  66. package/dist/result/match.mjs +4 -4
  67. package/dist/result/misc.mjs +2 -2
  68. package/dist/result/work/flow.d.mts +0 -3
  69. package/dist/result/work/flow.mjs +5 -5
  70. package/dist/result/work/pipe.d.mts +0 -3
  71. package/dist/result/work/pipe.mjs +3 -3
  72. package/dist/string/case.mjs +20 -20
  73. package/dist/string/fuzzy.mjs +23 -18
  74. package/dist/string/index.mjs +7 -7
  75. package/dist/string/normalize.mjs +14 -14
  76. package/dist/string/template.mjs +2 -2
  77. package/dist/value/clone.mjs +10 -10
  78. package/dist/value/smush.mjs +2 -2
  79. package/package.json +13 -5
  80. package/src/array/difference.ts +0 -73
  81. package/src/array/exists.ts +0 -93
  82. package/src/array/filter.ts +0 -182
  83. package/src/array/find.ts +0 -183
  84. package/src/array/first.ts +0 -196
  85. package/src/array/flatten.ts +0 -20
  86. package/src/array/from.ts +0 -129
  87. package/src/array/get.ts +0 -131
  88. package/src/array/group-by.ts +0 -369
  89. package/src/array/index.ts +0 -26
  90. package/src/array/insert.ts +0 -52
  91. package/src/array/intersection.ts +0 -72
  92. package/src/array/last.ts +0 -194
  93. package/src/array/match.ts +0 -436
  94. package/src/array/move.ts +0 -315
  95. package/src/array/partition.ts +0 -91
  96. package/src/array/push.ts +0 -23
  97. package/src/array/reverse.ts +0 -33
  98. package/src/array/select.ts +0 -260
  99. package/src/array/single.ts +0 -93
  100. package/src/array/slice.ts +0 -335
  101. package/src/array/sort.ts +0 -607
  102. package/src/array/splice.ts +0 -106
  103. package/src/array/swap.ts +0 -322
  104. package/src/array/to-map.ts +0 -371
  105. package/src/array/to-record.ts +0 -351
  106. package/src/array/to-set.ts +0 -80
  107. package/src/array/toggle.ts +0 -79
  108. package/src/array/union.ts +0 -72
  109. package/src/array/unique.ts +0 -67
  110. package/src/array/update.ts +0 -75
  111. package/src/beacon.ts +0 -378
  112. package/src/color/constants.ts +0 -137
  113. package/src/color/index.ts +0 -83
  114. package/src/color/instance.ts +0 -162
  115. package/src/color/misc/alpha.ts +0 -56
  116. package/src/color/misc/format.ts +0 -29
  117. package/src/color/misc/get.ts +0 -210
  118. package/src/color/misc/is.ts +0 -221
  119. package/src/color/misc/state.ts +0 -243
  120. package/src/color/models.ts +0 -389
  121. package/src/color/space/hex.ts +0 -184
  122. package/src/color/space/hsl.ts +0 -174
  123. package/src/color/space/hwb.ts +0 -153
  124. package/src/color/space/rgb.ts +0 -240
  125. package/src/function/assert.ts +0 -174
  126. package/src/function/index.ts +0 -2
  127. package/src/function/limit.ts +0 -83
  128. package/src/function/memoize.ts +0 -202
  129. package/src/function/once.ts +0 -200
  130. package/src/function/retry.ts +0 -175
  131. package/src/function/work.ts +0 -1007
  132. package/src/herald.ts +0 -216
  133. package/src/index.ts +0 -68
  134. package/src/internal/array/callbacks.ts +0 -46
  135. package/src/internal/array/chunk.ts +0 -51
  136. package/src/internal/array/compact.ts +0 -56
  137. package/src/internal/array/find.ts +0 -200
  138. package/src/internal/array/group.ts +0 -42
  139. package/src/internal/array/index-of.ts +0 -182
  140. package/src/internal/array/insert.ts +0 -80
  141. package/src/internal/array/overlap.ts +0 -35
  142. package/src/internal/array/sets.ts +0 -74
  143. package/src/internal/array/shuffle.ts +0 -33
  144. package/src/internal/array/update.ts +0 -52
  145. package/src/internal/function/misc.ts +0 -8
  146. package/src/internal/function/timer.ts +0 -168
  147. package/src/internal/is.ts +0 -244
  148. package/src/internal/math/aggregate.ts +0 -164
  149. package/src/internal/math/misc.ts +0 -28
  150. package/src/internal/number.ts +0 -129
  151. package/src/internal/random.ts +0 -49
  152. package/src/internal/result.ts +0 -92
  153. package/src/internal/sized.ts +0 -25
  154. package/src/internal/string.ts +0 -128
  155. package/src/internal/subscription.ts +0 -264
  156. package/src/internal/value/compare.ts +0 -170
  157. package/src/internal/value/equal.ts +0 -465
  158. package/src/internal/value/get.ts +0 -57
  159. package/src/internal/value/handlers.ts +0 -95
  160. package/src/internal/value/has.ts +0 -118
  161. package/src/internal/value/misc.ts +0 -125
  162. package/src/internal/value/partial.ts +0 -46
  163. package/src/internal/value/set.ts +0 -132
  164. package/src/is.ts +0 -182
  165. package/src/logger.ts +0 -230
  166. package/src/math.ts +0 -281
  167. package/src/models.ts +0 -286
  168. package/src/number.ts +0 -1
  169. package/src/promise/delay.ts +0 -62
  170. package/src/promise/helpers.ts +0 -96
  171. package/src/promise/index.ts +0 -300
  172. package/src/promise/misc.ts +0 -96
  173. package/src/promise/models.ts +0 -195
  174. package/src/promise/timed.ts +0 -91
  175. package/src/query.ts +0 -147
  176. package/src/queue.ts +0 -814
  177. package/src/random.ts +0 -125
  178. package/src/result/index.ts +0 -105
  179. package/src/result/match.ts +0 -124
  180. package/src/result/misc.ts +0 -129
  181. package/src/result/models.ts +0 -83
  182. package/src/result/work/flow.ts +0 -488
  183. package/src/result/work/pipe.ts +0 -496
  184. package/src/sized/map.ts +0 -110
  185. package/src/sized/set.ts +0 -107
  186. package/src/string/case.ts +0 -236
  187. package/src/string/fuzzy.ts +0 -444
  188. package/src/string/index.ts +0 -199
  189. package/src/string/match.ts +0 -80
  190. package/src/string/normalize.ts +0 -205
  191. package/src/string/template.ts +0 -161
  192. package/src/value/clone.ts +0 -319
  193. package/src/value/collection.ts +0 -63
  194. package/src/value/diff.ts +0 -232
  195. package/src/value/freeze.ts +0 -322
  196. package/src/value/handle.ts +0 -3
  197. package/src/value/index.ts +0 -5
  198. package/src/value/merge.ts +0 -278
  199. package/src/value/omit.ts +0 -20
  200. package/src/value/pick.ts +0 -20
  201. package/src/value/shake.ts +0 -45
  202. package/src/value/smush.ts +0 -89
  203. package/src/value/transform.ts +0 -153
  204. package/src/value/unsmush.ts +0 -84
package/src/queue.ts DELETED
@@ -1,814 +0,0 @@
1
- import {getNumberOrDefault} from './internal/number';
2
- import type {GenericAsyncCallback, GenericCallback} from './models';
3
-
4
- // #region Types
5
-
6
- type HandleType = 'clear' | 'pause' | 'resume';
7
-
8
- /**
9
- * A queue that can be used to manage (a)synchronous tasks with a specific key
10
- */
11
- export type KeyedQueue<
12
- Callback extends GenericCallback | GenericAsyncCallback,
13
- CallbackParameters extends unknown[] = Parameters<Callback>,
14
- > = {
15
- /**
16
- * Get keys of all active queues
17
- */
18
- get active(): string[];
19
-
20
- /**
21
- * Does the queue automatically start when the first item is added?
22
- */
23
- get autostart(): boolean;
24
-
25
- /**
26
- * Maximum number of runners to process the queue concurrently
27
- */
28
- get concurrency(): number;
29
-
30
- /**
31
- * Get keys of all empty queues
32
- */
33
- get empty(): string[];
34
-
35
- /**
36
- * Get keys of all full queues
37
- */
38
- get full(): string[];
39
-
40
- /**
41
- * Number of items in all queues
42
- */
43
- get items(): Record<string, number>;
44
-
45
- /**
46
- * Keys of all queues
47
- */
48
- get keys(): string[];
49
-
50
- /**
51
- * Maximum number of items allowed in the queue
52
- */
53
- get maximum(): number;
54
-
55
- /**
56
- * Are all queues paused?
57
- */
58
- get paused(): string[];
59
-
60
- /**
61
- * Number of queues
62
- */
63
- get queues(): number;
64
-
65
- /**
66
- * Queue an item for a specific key
67
- *
68
- * @param key Key to queue the item for
69
- * @param parameters Parameters to use when item runs
70
- * @param signal Optional signal to abort the item
71
- * @returns Queued item
72
- */
73
- add(
74
- key: string,
75
- parameters: Tail<CallbackParameters>,
76
- signal?: AbortSignal,
77
- ): Queued<ReturnType<Callback>>;
78
-
79
- /**
80
- * Clear all items for a specific key _(or all items for all keys, if no key is provided)_
81
- *
82
- * @param key Optional key to clear the queue for
83
- */
84
- clear(key?: string): void;
85
-
86
- /**
87
- * Get the queue for a specific key
88
- *
89
- * @param key Key to get the queue for
90
- * @returns Queue for the key, or `undefined` if it doesn't exist
91
- */
92
- get(key: string): Queue<Callback, Tail<CallbackParameters>> | undefined;
93
-
94
- /**
95
- * Pause the queue for a specific key _(or all queues, if no key is provided)_
96
- *
97
- * @param key Optional key to pause the queue for
98
- */
99
- pause(key?: string): void;
100
-
101
- /**
102
- * Remove a specific item for a specific key
103
- *
104
- * @param key Key to remove the item for
105
- * @param id ID of the item to remove
106
- */
107
- remove(key: string, id: number): void;
108
-
109
- /**
110
- * Remove a queue and its items for a specific key
111
- *
112
- * _(To remove all items for a specific key, use `clear()` instead)_
113
- *
114
- * @param key Key to remove the queue for
115
- */
116
- remove(key: string): void;
117
-
118
- /**
119
- * Remove all queues and their items
120
- */
121
- remove(): void;
122
-
123
- /**
124
- * Resume the queue for a specific key _(or all queues, if no key is provided)_
125
- *
126
- * @param key Optional key to resume the queue for
127
- */
128
- resume(key?: string): void;
129
- };
130
-
131
- type KeyedQueueState = {
132
- callback: GenericCallback | GenericAsyncCallback;
133
- options: Required<QueueOptions>;
134
- queues: Map<string, Queue<GenericAsyncCallback, Tail<unknown[]>>>;
135
- };
136
-
137
- /**
138
- * A queue that can be used to manage (a)synchronous tasks
139
- */
140
- export type Queue<
141
- Callback extends GenericCallback | GenericAsyncCallback,
142
- CallbackParameters extends unknown[] = Parameters<Callback>,
143
- > = {
144
- /**
145
- * Is the queue active?
146
- */
147
- get active(): boolean;
148
-
149
- /**
150
- * Does the queue automatically start when the first item is added?
151
- */
152
- get autostart(): boolean;
153
-
154
- /**
155
- * Maximum number of runners to process the queue concurrently
156
- */
157
- get concurrency(): number;
158
-
159
- /**
160
- * Is the queue empty?
161
- */
162
- get empty(): boolean;
163
-
164
- /**
165
- * Is the queue full?
166
- */
167
- get full(): boolean;
168
-
169
- /**
170
- * Maximum number of items allowed in the queue
171
- */
172
- get maximum(): number;
173
-
174
- /**
175
- * Is the queue paused?
176
- */
177
- get paused(): boolean;
178
-
179
- /**
180
- * Number of items in the queue
181
- */
182
- get size(): number;
183
-
184
- /**
185
- * Add an item to the queue
186
- *
187
- * @param parameters Parameters to use when item runs
188
- * @param signal Optional signal to abort the item
189
- * @returns Queued item
190
- */
191
- add(parameters: CallbackParameters, signal?: AbortSignal): Queued<ReturnType<Callback>>;
192
-
193
- /**
194
- * Remove and reject all items in the queue
195
- */
196
- clear(): void;
197
-
198
- /**
199
- * Pause the queue
200
- *
201
- * - Currently running items will not be stopped
202
- * - New added items will not run until the queue is resumed
203
- */
204
- pause(): void;
205
-
206
- /**
207
- * Remove and reject a specific item in the queue
208
- *
209
- * @param id ID of queued item
210
- */
211
- remove(id: number): void;
212
-
213
- /**
214
- * Resume the queue
215
- */
216
- resume(): void;
217
- };
218
-
219
- type QueueState = {
220
- callback: GenericCallback | GenericAsyncCallback;
221
- handled: GenericCallback[];
222
- id: number;
223
- items: Array<QueuedItem>;
224
- key: string | undefined;
225
- options: Required<QueueOptions>;
226
- paused: boolean;
227
- runners: number;
228
- };
229
-
230
- /**
231
- * An error thrown by the Queue when an operation fails
232
- */
233
- export class QueueError extends Error {
234
- constructor(message: string) {
235
- super(message);
236
-
237
- this.name = ERROR_NAME;
238
- }
239
- }
240
-
241
- export type QueueOptions = {
242
- /**
243
- * Automatically start processing the queue when the first item is added _(defaults to `true`)_
244
- */
245
- autostart?: boolean;
246
- /**
247
- * Number of runners to process the queue concurrently _(defaults to `1`)_
248
- */
249
- concurrency?: number;
250
- /**
251
- * Maximum number of items allowed in the queue _(defaults to `0`, which means no limit)_
252
- */
253
- maximum?: number;
254
- };
255
-
256
- /**
257
- * A queued item
258
- */
259
- export type Queued<Value> = {
260
- /**
261
- * ID of the queued item _(can be used to remove it from the queue)_
262
- */
263
- readonly id: number;
264
- /**
265
- * Queued promise
266
- */
267
- readonly promise: Promise<Value extends Promise<infer Result> ? Result : Value>;
268
- };
269
-
270
- type QueuedItem = {
271
- abort?: () => void;
272
- id: number;
273
- key?: string;
274
- parameters: unknown[];
275
- promise: Promise<unknown>;
276
- reject: (reason?: unknown) => void;
277
- resolve: (value: unknown) => void;
278
- signal?: AbortSignal;
279
- };
280
-
281
- type StatusKey = 'active' | 'empty' | 'full' | 'paused';
282
-
283
- type Tail<Values extends any[]> = Values extends [infer _, ...infer Rest] ? Rest : never;
284
-
285
- // #endregion
286
-
287
- // #region Functions
288
-
289
- function createQueue(
290
- callback: GenericAsyncCallback,
291
- options?: QueueOptions,
292
- key?: string,
293
- ): Queue<never, never> {
294
- if (typeof callback !== 'function') {
295
- throw new TypeError(MESSAGE_CALLBACK);
296
- }
297
-
298
- const state: QueueState = {
299
- callback,
300
- key,
301
- handled: [],
302
- id: 0,
303
- items: [],
304
- options: getOptions(options),
305
- paused: !getBooleanOrDefault(options?.autostart, true),
306
- runners: 0,
307
- };
308
-
309
- const instance = {
310
- add: (parameters: unknown[], signal?: AbortSignal) => {
311
- if ((instance as Queue<GenericCallback>).full) {
312
- throw new QueueError(MESSAGE_MAXIMUM);
313
- }
314
-
315
- const abortSignal = signal instanceof AbortSignal ? signal : undefined;
316
-
317
- if (abortSignal?.aborted ?? false) {
318
- throw new Error(abortSignal!.reason);
319
- }
320
-
321
- const id = identify(state);
322
-
323
- let rejector: (reason?: unknown) => void;
324
- let resolver: (value: unknown) => void;
325
-
326
- const promise = new Promise<unknown>((resolve, reject) => {
327
- rejector = reject;
328
- resolver = resolve;
329
- });
330
-
331
- const aborter = abortSignal == null ? undefined : () => rejector(abortSignal.reason);
332
-
333
- signal?.addEventListener(EVENT_NAME, aborter!, EVENT_OPTIONS);
334
-
335
- state.items.push({
336
- id,
337
- parameters,
338
- promise,
339
- abort: aborter,
340
- key: state.key,
341
- reject: rejector!,
342
- resolve: resolver!,
343
- signal: abortSignal,
344
- });
345
-
346
- if (state.options.autostart) {
347
- void run(state);
348
- }
349
-
350
- return {id, promise};
351
- },
352
- clear: () => {
353
- const items = state.items.splice(0);
354
- const {length} = items;
355
-
356
- for (let index = 0; index < length; index += 1) {
357
- const {abort, reject, signal} = items[index];
358
-
359
- reject(new QueueError(MESSAGE_CLEAR));
360
-
361
- signal?.removeEventListener(EVENT_NAME, abort!);
362
- }
363
- },
364
- pause: () => {
365
- state.paused = true;
366
- },
367
- remove: (id: number) => {
368
- const index = state.items.findIndex(item => item.id === id);
369
-
370
- if (index > -1) {
371
- const {abort, reject, signal} = state.items.splice(index, 1)[0];
372
-
373
- reject(new QueueError(MESSAGE_REMOVE));
374
-
375
- signal?.removeEventListener(EVENT_NAME, abort!);
376
- }
377
- },
378
- resume: () => {
379
- if (state.paused) {
380
- const handled = state.handled.splice(0);
381
- const {length} = handled;
382
-
383
- for (let index = 0; index < length; index += 1) {
384
- handled[index]();
385
- }
386
- }
387
-
388
- state.paused = false;
389
-
390
- const length = Math.min(state.options.concurrency, state.items.length);
391
-
392
- for (let index = 0; index < length; index += 1) {
393
- void run(state);
394
- }
395
- },
396
- };
397
-
398
- Object.defineProperties(instance, {
399
- [KEY_QUEUE]: {
400
- enumerable: false,
401
- value: NAME_QUEUE,
402
- },
403
- active: {
404
- enumerable: true,
405
- get: () => state.runners > 0,
406
- },
407
- autostart: {
408
- enumerable: true,
409
- get: () => state.options.autostart,
410
- },
411
- concurrency: {
412
- enumerable: true,
413
- get: () => state.options.concurrency,
414
- },
415
- empty: {
416
- enumerable: true,
417
- get: () => state.items.length === 0,
418
- },
419
- full: {
420
- enumerable: true,
421
- get: () => state.options.maximum > 0 && state.items.length >= state.options.maximum,
422
- },
423
- maximum: {
424
- enumerable: true,
425
- get: () => state.options.maximum,
426
- },
427
- paused: {
428
- enumerable: true,
429
- get: () => state.paused,
430
- },
431
- size: {
432
- enumerable: true,
433
- get: () => state.items.length,
434
- },
435
- });
436
-
437
- return Object.freeze(instance) as Queue<GenericCallback>;
438
- }
439
-
440
- function getBooleanOrDefault(value: unknown, defaultValue: boolean): boolean {
441
- return typeof value === 'boolean' ? value : defaultValue;
442
- }
443
-
444
- function getItems(state: KeyedQueueState): Record<string, number> {
445
- const size: Record<string, number> = {};
446
-
447
- const queues = state.queues.entries();
448
-
449
- for (const [key, queue] of queues) {
450
- size[key] = queue.size;
451
- }
452
-
453
- return size;
454
- }
455
-
456
- function getOptions(input?: QueueOptions): Required<QueueOptions> {
457
- const options = typeof input === 'object' && input != null ? input : {};
458
-
459
- return {
460
- autostart: getBooleanOrDefault(options.autostart, true),
461
- concurrency: getNumberOrDefault(options.concurrency, 1, 1),
462
- maximum: getNumberOrDefault(options.maximum, 0),
463
- };
464
- }
465
-
466
- function getQueue(state: KeyedQueueState, key: string, add: true): Queue<GenericCallback>;
467
-
468
- function getQueue(state: KeyedQueueState, key: string): Queue<GenericCallback> | undefined;
469
-
470
- function getQueue(
471
- state: KeyedQueueState,
472
- key: string,
473
- add?: boolean,
474
- ): Queue<GenericCallback> | undefined {
475
- if (typeof key !== 'string' || key.trim().length === 0) {
476
- throw new TypeError(MESSAGE_KEY);
477
- }
478
-
479
- let queue = state.queues.get(key);
480
-
481
- if (queue == null && add === true) {
482
- queue = createQueue(state.callback, state.options, key);
483
-
484
- state.queues.set(key, queue);
485
- }
486
-
487
- return queue;
488
- }
489
-
490
- function getStatus(state: KeyedQueueState, status: StatusKey): string[] {
491
- const queues = state.queues.entries();
492
-
493
- const result: string[] = [];
494
-
495
- for (const [key, queue] of queues) {
496
- if (queue[status]) {
497
- result.push(key);
498
- }
499
- }
500
-
501
- return result;
502
- }
503
-
504
- function handleQueuedResult(item: QueuedItem, error: boolean, result: unknown): void {
505
- item.signal?.removeEventListener(EVENT_NAME, item.abort!);
506
-
507
- if (item.signal?.aborted ?? false) {
508
- item.reject();
509
-
510
- return;
511
- }
512
-
513
- if (error) {
514
- item.reject(result);
515
-
516
- return;
517
- }
518
-
519
- item.resolve(result);
520
- }
521
-
522
- function handleQueues(state: KeyedQueueState, type: HandleType, key?: string): void {
523
- if (typeof key === 'string') {
524
- getQueue(state, key)?.[type]();
525
-
526
- return;
527
- }
528
-
529
- const queues = state.queues.values();
530
-
531
- for (const queue of queues) {
532
- queue[type]();
533
- }
534
- }
535
-
536
- function identify(state: QueueState): number {
537
- state.id += 1;
538
-
539
- return state.id;
540
- }
541
-
542
- /**
543
- * Is the value keyed queue?
544
- *
545
- * @param value Value to check
546
- * @returns `true` if the value is a keyed queue, otherwise `false`
547
- */
548
- export function isKeyedQueue(value: unknown): value is KeyedQueue<GenericAsyncCallback> {
549
- return isQueueInstance(NAME_KEYED, value);
550
- }
551
-
552
- /**
553
- * Is the value a queue?
554
- *
555
- * @param value Value to check
556
- * @returns `true` if the value is a queue, otherwise `false`
557
- */
558
- export function isQueue(value: unknown): value is Queue<GenericCallback | GenericAsyncCallback> {
559
- return isQueueInstance(NAME_QUEUE, value);
560
- }
561
-
562
- export function isQueueInstance<Instance>(name: string, value: unknown): value is Instance {
563
- return (
564
- typeof value === 'object' &&
565
- value != null &&
566
- (value as Record<string, unknown>)[KEY_QUEUE] === name
567
- );
568
- }
569
-
570
- /**
571
- * Create a keyed queue for an asynchronous callback function, where each key has its own queue
572
- *
573
- * @param callback Callback function for queued items
574
- * @param options Queue options
575
- */
576
- export function keyedQueue<Callback extends (key: string, ...parameters: any[]) => Promise<void>>(
577
- callback: Callback,
578
- options?: QueueOptions,
579
- ): KeyedQueue<Callback, Parameters<Callback>>;
580
-
581
- /**
582
- * Create a keyed queue for an asynchronous callback function, where each key has its own queue
583
- *
584
- * @param callback Callback function for queued items
585
- * @param options Queue options
586
- */
587
- export function keyedQueue<Callback extends (key: string, ...parameters: any[]) => void>(
588
- callback: Callback,
589
- options?: QueueOptions,
590
- ): KeyedQueue<Callback, Parameters<Callback>>;
591
-
592
- export function keyedQueue<Callback extends (key: string, ...parameters: any[]) => Promise<void>>(
593
- callback: Callback,
594
- options?: QueueOptions,
595
- ): KeyedQueue<Callback, Parameters<Callback>> {
596
- if (typeof callback !== 'function') {
597
- throw new TypeError(MESSAGE_CALLBACK);
598
- }
599
-
600
- const state: KeyedQueueState = {
601
- callback,
602
- options: getOptions(options),
603
- queues: new Map(),
604
- };
605
-
606
- const instance = {
607
- add: (key: string, parameters: Tail<unknown[]>, signal?: AbortSignal) =>
608
- getQueue(state, key, true).add(parameters, signal),
609
- clear: (key?: string) => {
610
- handleQueues(state, HANDLE_CLEAR, key);
611
- },
612
- get: (key: string) => getQueue(state, key),
613
- pause: (key?: string): void => {
614
- handleQueues(state, HANDLE_PAUSE, key);
615
- },
616
- remove: (key?: string, id?: number): void => removeQueue(state, key, id),
617
- resume: (key?: string): void => {
618
- handleQueues(state, HANDLE_RESUME, key);
619
- },
620
- };
621
-
622
- Object.defineProperties(instance, {
623
- [KEY_QUEUE]: {
624
- enumerable: false,
625
- value: NAME_KEYED,
626
- },
627
- active: {
628
- enumerable: true,
629
- get: () => getStatus(state, STATUS_ACTIVE),
630
- },
631
- autostart: {
632
- enumerable: true,
633
- get: () => state.options.autostart,
634
- },
635
- concurrency: {
636
- enumerable: true,
637
- get: () => state.options.concurrency,
638
- },
639
- empty: {
640
- enumerable: true,
641
- get: () => getStatus(state, STATUS_EMPTY),
642
- },
643
- full: {
644
- enumerable: true,
645
- get: () => getStatus(state, STATUS_FULL),
646
- },
647
- items: {
648
- enumerable: true,
649
- get: () => getItems(state),
650
- },
651
- keys: {
652
- enumerable: true,
653
- get: () => [...state.queues.keys()],
654
- },
655
- maximum: {
656
- enumerable: true,
657
- get: () => state.options.maximum,
658
- },
659
- paused: {
660
- enumerable: true,
661
- get: () => getStatus(state, STATUS_PAUSED),
662
- },
663
- queues: {
664
- enumerable: true,
665
- get: () => state.queues.size,
666
- },
667
- });
668
-
669
- return Object.freeze(instance) as unknown as KeyedQueue<Callback, Parameters<Callback>>;
670
- }
671
-
672
- /**
673
- * Create a queue for an asynchronous callback function
674
- *
675
- * @param callback Callback function for queued items
676
- * @param options Queue options
677
- * @returns Queue instance
678
- */
679
- export function queue<Callback extends GenericAsyncCallback>(
680
- callback: Callback,
681
- options?: QueueOptions,
682
- ): Queue<Callback, Parameters<Callback>>;
683
-
684
- /**
685
- * Create a queue for a synchronous callback function
686
- *
687
- * @param callback Callback function for queued items
688
- * @param options Queue options
689
- * @returns Queue instance
690
- */
691
- export function queue<Callback extends GenericCallback>(
692
- callback: Callback,
693
- options?: QueueOptions,
694
- ): Queue<Callback, Parameters<Callback>>;
695
-
696
- export function queue<Callback extends GenericCallback | GenericAsyncCallback>(
697
- callback: Callback,
698
- options?: QueueOptions,
699
- ): Queue<Callback, Parameters<Callback>> {
700
- return createQueue(callback, options);
701
- }
702
-
703
- queue.keyed = keyedQueue;
704
-
705
- function removeQueue(state: KeyedQueueState, key?: string, id?: number): void {
706
- if (key == null) {
707
- handleQueues(state, HANDLE_CLEAR);
708
-
709
- state.queues.clear();
710
-
711
- return;
712
- }
713
-
714
- const queue = getQueue(state, key);
715
-
716
- if (queue == null) {
717
- return;
718
- }
719
-
720
- if (typeof id === 'number') {
721
- queue.remove(id);
722
-
723
- return;
724
- }
725
-
726
- queue.clear();
727
-
728
- state.queues.delete(key);
729
- }
730
-
731
- async function run(state: QueueState): Promise<void> {
732
- if (state.paused || state.runners >= state.options.concurrency) {
733
- return;
734
- }
735
-
736
- state.runners += 1;
737
-
738
- let item = state.items.shift();
739
-
740
- while (item != null) {
741
- let error = false;
742
-
743
- let result: unknown;
744
-
745
- try {
746
- if (!(item.signal?.aborted ?? false)) {
747
- const parameters = item.key == null ? item.parameters : [item.key, ...item.parameters];
748
-
749
- result = await state.callback(...parameters);
750
- }
751
- } catch (thrown) {
752
- error = true;
753
- result = thrown;
754
- }
755
-
756
- if (state.paused) {
757
- const paused = item;
758
-
759
- state.handled.push(() => {
760
- handleQueuedResult(paused, error, result);
761
- });
762
-
763
- break;
764
- }
765
-
766
- handleQueuedResult(item, error, result);
767
-
768
- item = state.items.shift();
769
- }
770
-
771
- state.runners -= 1;
772
- }
773
-
774
- // #endregion
775
-
776
- // #region Variables
777
-
778
- const ERROR_NAME = 'QueueError';
779
-
780
- const EVENT_NAME = 'abort';
781
-
782
- const EVENT_OPTIONS = {once: true};
783
-
784
- const KEY_QUEUE = '$queue';
785
-
786
- const HANDLE_CLEAR: HandleType = 'clear';
787
-
788
- const HANDLE_PAUSE: HandleType = 'pause';
789
-
790
- const HANDLE_RESUME: HandleType = 'resume';
791
-
792
- const MESSAGE_CALLBACK = 'A Queue requires a callback function';
793
-
794
- const MESSAGE_CLEAR = 'Queue was cleared';
795
-
796
- const MESSAGE_KEY = 'Key must be a non-empty string';
797
-
798
- const MESSAGE_MAXIMUM = 'Queue has reached its maximum size';
799
-
800
- const MESSAGE_REMOVE = 'Item removed from queue';
801
-
802
- const NAME_KEYED = 'keyedQueue';
803
-
804
- const NAME_QUEUE = 'queue';
805
-
806
- const STATUS_ACTIVE: StatusKey = 'active';
807
-
808
- const STATUS_EMPTY: StatusKey = 'empty';
809
-
810
- const STATUS_FULL: StatusKey = 'full';
811
-
812
- const STATUS_PAUSED: StatusKey = 'paused';
813
-
814
- // #endregion