@oscarpalmer/atoms 0.131.0 → 0.133.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.
@@ -1971,6 +1971,239 @@ function round(value, decimals) {
1971
1971
  function sum(array, key) {
1972
1972
  return getAggregated("sum", array, key);
1973
1973
  }
1974
+ var PromiseTimeoutError = class extends Error {
1975
+ constructor() {
1976
+ super(MESSAGE_TIMEOUT);
1977
+ this.name = NAME;
1978
+ }
1979
+ };
1980
+ /**
1981
+ * Create a delayed promise that resolves after a certain amount of time
1982
+ * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
1983
+ * @returns A promise that resolves after the delay
1984
+ */
1985
+ function delay(time) {
1986
+ return new Promise((resolve) => setTimeout(resolve, getNumberOrDefault$1(time)));
1987
+ }
1988
+ function getBooleanOrDefault$1(value, defaultValue) {
1989
+ return typeof value === "boolean" ? value : defaultValue;
1990
+ }
1991
+ function getNumberOrDefault$1(value) {
1992
+ return typeof value === "number" ? value : 0;
1993
+ }
1994
+ async function promises(items, eager) {
1995
+ const actual = items.filter((item) => item instanceof Promise);
1996
+ if (actual.length === 0) return actual;
1997
+ const isEager = getBooleanOrDefault$1(eager, false);
1998
+ const { length } = actual;
1999
+ const data = {
2000
+ last: length - 1,
2001
+ result: []
2002
+ };
2003
+ let handlers;
2004
+ return new Promise((resolve, reject) => {
2005
+ handlers = {
2006
+ reject,
2007
+ resolve
2008
+ };
2009
+ for (let index = 0; index < length; index += 1) actual[index].then((value) => resolveResult(index, data, handlers, value, isEager)).catch((reason) => rejectResult(index, data, handlers, reason, isEager));
2010
+ });
2011
+ }
2012
+ function rejectResult(index, data, handlers, reason, eager) {
2013
+ if (eager) handlers.reject(reason);
2014
+ else {
2015
+ data.result[index] = {
2016
+ status: TYPE_REJECTED,
2017
+ reason
2018
+ };
2019
+ if (index === data.last) handlers.resolve(data.result);
2020
+ }
2021
+ }
2022
+ function resolveResult(index, data, handlers, value, eager) {
2023
+ data.result[index] = eager ? value : {
2024
+ status: TYPE_FULFILLED,
2025
+ value
2026
+ };
2027
+ if (index === data.last) handlers.resolve(data.result);
2028
+ }
2029
+ function timed(promise, timeout) {
2030
+ if (!(promise instanceof Promise)) throw new TypeError(MESSAGE_EXPECTATION);
2031
+ if (getNumberOrDefault$1(timeout) <= 0) return promise;
2032
+ return Promise.race([promise, new Promise((_, reject) => setTimeout(() => reject(new PromiseTimeoutError()), timeout))]);
2033
+ }
2034
+ const MESSAGE_EXPECTATION = "Timed function expected a Promise";
2035
+ const MESSAGE_TIMEOUT = "Promise timed out";
2036
+ const NAME = "PromiseTimeoutError";
2037
+ const TYPE_FULFILLED = "fulfilled";
2038
+ const TYPE_REJECTED = "rejected";
2039
+ var Queue = class {
2040
+ #callback;
2041
+ #handled = [];
2042
+ #id = 0;
2043
+ #items = [];
2044
+ #options;
2045
+ #paused;
2046
+ #runners = 0;
2047
+ /**
2048
+ * Is the queue active?
2049
+ */
2050
+ get active() {
2051
+ return this.#runners > 0;
2052
+ }
2053
+ /**
2054
+ * Is the queue empty?
2055
+ */
2056
+ get empty() {
2057
+ return this.#items.length === 0;
2058
+ }
2059
+ /**
2060
+ * Is the queue full?
2061
+ */
2062
+ get full() {
2063
+ return this.#options.maximum > 0 && this.#items.length >= this.#options.maximum;
2064
+ }
2065
+ /**
2066
+ * Is the queue paused?
2067
+ */
2068
+ get paused() {
2069
+ return this.#paused;
2070
+ }
2071
+ /**
2072
+ * Number of items in the queue
2073
+ */
2074
+ get size() {
2075
+ return this.#items.length;
2076
+ }
2077
+ constructor(callback, options) {
2078
+ this.#callback = callback;
2079
+ this.#options = options;
2080
+ this.#paused = !options.autostart;
2081
+ }
2082
+ /**
2083
+ * Add an item to the queue
2084
+ * @param parameters Parameters to use when item runs
2085
+ * @returns Queued item
2086
+ */
2087
+ add(...parameters) {
2088
+ if (this.full) throw new QueueError(MESSAGE_MAXIMUM);
2089
+ let rejector;
2090
+ let resolver;
2091
+ const id = this.#identify();
2092
+ const promise = new Promise((resolve, reject) => {
2093
+ rejector = reject;
2094
+ resolver = resolve;
2095
+ });
2096
+ this.#items.push({
2097
+ id,
2098
+ parameters,
2099
+ promise,
2100
+ reject: rejector,
2101
+ resolve: resolver
2102
+ });
2103
+ if (this.#options.autostart) this.#run();
2104
+ return {
2105
+ id,
2106
+ promise
2107
+ };
2108
+ }
2109
+ /**
2110
+ * Remove and reject all items in the queue
2111
+ */
2112
+ clear() {
2113
+ const items = this.#items.splice(0);
2114
+ const { length } = items;
2115
+ for (let index = 0; index < length; index += 1) items[index].reject(new QueueError(MESSAGE_CLEAR));
2116
+ }
2117
+ /**
2118
+ * Pause the queue
2119
+ *
2120
+ * - Currently running items will not be stopped
2121
+ * - New added items will not run until the queue is resumed
2122
+ */
2123
+ pause() {
2124
+ this.#paused = true;
2125
+ }
2126
+ /**
2127
+ * Remove and reject a specific item in the queue
2128
+ * @param id ID of queued item
2129
+ */
2130
+ remove(id) {
2131
+ const index = this.#items.findIndex((item) => item.id === id);
2132
+ if (index > -1) {
2133
+ const [item] = this.#items.splice(index, 1);
2134
+ item.reject(new QueueError(MESSAGE_REMOVE));
2135
+ }
2136
+ }
2137
+ /**
2138
+ * Resume the queue
2139
+ */
2140
+ resume() {
2141
+ if (this.#paused) {
2142
+ const handled = this.#handled.splice(0);
2143
+ const { length } = handled;
2144
+ for (let index = 0; index < length; index += 1) handled[index]();
2145
+ }
2146
+ this.#paused = false;
2147
+ const length = Math.min(this.#options.concurrency, this.#items.length);
2148
+ for (let index = 0; index < length; index += 1) this.#run();
2149
+ }
2150
+ #identify() {
2151
+ this.#id += 1;
2152
+ return this.#id;
2153
+ }
2154
+ async #run() {
2155
+ if (this.#paused || this.#runners >= this.#options.concurrency) return;
2156
+ this.#runners += 1;
2157
+ let item = this.#items.shift();
2158
+ while (item != null) {
2159
+ let handler;
2160
+ let result;
2161
+ try {
2162
+ result = await this.#callback(...item.parameters);
2163
+ handler = item.resolve;
2164
+ } catch (thrown) {
2165
+ result = thrown;
2166
+ handler = item.reject;
2167
+ }
2168
+ if (this.#paused) {
2169
+ this.#handled.push(() => handler(result));
2170
+ break;
2171
+ }
2172
+ handler(result);
2173
+ item = this.#items.shift();
2174
+ }
2175
+ this.#runners -= 1;
2176
+ }
2177
+ };
2178
+ var QueueError = class extends Error {
2179
+ constructor(message) {
2180
+ super(message);
2181
+ this.name = ERROR_NAME;
2182
+ }
2183
+ };
2184
+ function getBooleanOrDefault(value, defaultValue) {
2185
+ return typeof value === "boolean" ? value : defaultValue;
2186
+ }
2187
+ function getNumberOrDefault(value, defaultValue) {
2188
+ return typeof value === "number" && value > 0 ? Math.floor(value) : defaultValue;
2189
+ }
2190
+ function getOptions(input) {
2191
+ const options = typeof input === "object" && input != null ? input : {};
2192
+ return {
2193
+ autostart: getBooleanOrDefault(options.autostart, true),
2194
+ concurrency: getNumberOrDefault(options.concurrency, 1),
2195
+ maximum: getNumberOrDefault(options.maximum, 0)
2196
+ };
2197
+ }
2198
+ function queue(callback, options) {
2199
+ if (typeof callback !== "function") throw new TypeError(MESSAGE_CALLBACK);
2200
+ return new Queue(callback, getOptions(options));
2201
+ }
2202
+ const ERROR_NAME = "QueueError";
2203
+ const MESSAGE_CALLBACK = "A Queue requires a callback function";
2204
+ const MESSAGE_CLEAR = "Queue was cleared";
2205
+ const MESSAGE_MAXIMUM = "Queue has reached its maximum size";
2206
+ const MESSAGE_REMOVE = "Item removed from queue";
1974
2207
  function findKey(needle, haystack) {
1975
2208
  const keys = Object.keys(haystack);
1976
2209
  const index = keys.map((key) => key.toLowerCase()).indexOf(needle.toLowerCase());
@@ -2980,4 +3213,4 @@ function unsmush(value) {
2980
3213
  }
2981
3214
  return unsmushed;
2982
3215
  }
2983
- export { frame_rate_default as FRAME_RATE_MS, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, createUuid, debounce, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, includes, indexOf, insert, isArrayOrPlainObject, isColor, isEmpty, isError, isHexColor, isHslColor, isHslLike, isHslaColor, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, memoize, merge, min, noop, ok, parse, partial, pascalCase, push, result, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, unique, unsmush, unwrap, upperCase, words };
3216
+ export { frame_rate_default as FRAME_RATE_MS, PromiseTimeoutError, QueueError, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, createUuid, debounce, delay, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, includes, indexOf, insert, isArrayOrPlainObject, isColor, isEmpty, isError, isHexColor, isHslColor, isHslLike, isHslaColor, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, memoize, merge, min, noop, ok, parse, partial, pascalCase, promises, push, queue, result, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, unique, unsmush, unwrap, upperCase, words };
package/dist/index.js CHANGED
@@ -37,6 +37,8 @@ import { SizedMap, SizedSet } from "./sized.js";
37
37
  import { debounce, memoize, throttle } from "./function.js";
38
38
  import { logger } from "./logger.js";
39
39
  import { average, count, min, round, sum } from "./math.js";
40
+ import { PromiseTimeoutError, delay, promises, timed } from "./promise.js";
41
+ import { QueueError, queue } from "./queue.js";
40
42
  import { setValue } from "./internal/value/set.js";
41
43
  import { fromQuery, toQuery } from "./query.js";
42
44
  import { getRandomBoolean, getRandomCharacters, getRandomColor, getRandomHex, getRandomItem, getRandomItems } from "./random.js";
@@ -54,4 +56,4 @@ import { partial } from "./value/partial.js";
54
56
  import { smush } from "./value/smush.js";
55
57
  import { unsmush } from "./value/unsmush.js";
56
58
  import "./value/index.js";
57
- export { frame_rate_default as FRAME_RATE_MS, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, createUuid, debounce, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, includes, indexOf, insert, isArrayOrPlainObject, isColor, isEmpty, isError, isHexColor, isHslColor, isHslLike, isHslaColor, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, memoize, merge, min, noop, ok, parse, partial, pascalCase, push, result, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, unique, unsmush, unwrap, upperCase, words };
59
+ export { frame_rate_default as FRAME_RATE_MS, PromiseTimeoutError, QueueError, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, createUuid, debounce, delay, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, includes, indexOf, insert, isArrayOrPlainObject, isColor, isEmpty, isError, isHexColor, isHslColor, isHslLike, isHslaColor, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, memoize, merge, min, noop, ok, parse, partial, pascalCase, promises, push, queue, result, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, unique, unsmush, unwrap, upperCase, words };
@@ -0,0 +1,66 @@
1
+ var PromiseTimeoutError = class extends Error {
2
+ constructor() {
3
+ super(MESSAGE_TIMEOUT);
4
+ this.name = NAME;
5
+ }
6
+ };
7
+ /**
8
+ * Create a delayed promise that resolves after a certain amount of time
9
+ * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
10
+ * @returns A promise that resolves after the delay
11
+ */
12
+ function delay(time) {
13
+ return new Promise((resolve) => setTimeout(resolve, getNumberOrDefault(time)));
14
+ }
15
+ function getBooleanOrDefault(value, defaultValue) {
16
+ return typeof value === "boolean" ? value : defaultValue;
17
+ }
18
+ function getNumberOrDefault(value) {
19
+ return typeof value === "number" ? value : 0;
20
+ }
21
+ async function promises(items, eager) {
22
+ const actual = items.filter((item) => item instanceof Promise);
23
+ if (actual.length === 0) return actual;
24
+ const isEager = getBooleanOrDefault(eager, false);
25
+ const { length } = actual;
26
+ const data = {
27
+ last: length - 1,
28
+ result: []
29
+ };
30
+ let handlers;
31
+ return new Promise((resolve, reject) => {
32
+ handlers = {
33
+ reject,
34
+ resolve
35
+ };
36
+ for (let index = 0; index < length; index += 1) actual[index].then((value) => resolveResult(index, data, handlers, value, isEager)).catch((reason) => rejectResult(index, data, handlers, reason, isEager));
37
+ });
38
+ }
39
+ function rejectResult(index, data, handlers, reason, eager) {
40
+ if (eager) handlers.reject(reason);
41
+ else {
42
+ data.result[index] = {
43
+ status: TYPE_REJECTED,
44
+ reason
45
+ };
46
+ if (index === data.last) handlers.resolve(data.result);
47
+ }
48
+ }
49
+ function resolveResult(index, data, handlers, value, eager) {
50
+ data.result[index] = eager ? value : {
51
+ status: TYPE_FULFILLED,
52
+ value
53
+ };
54
+ if (index === data.last) handlers.resolve(data.result);
55
+ }
56
+ function timed(promise, timeout) {
57
+ if (!(promise instanceof Promise)) throw new TypeError(MESSAGE_EXPECTATION);
58
+ if (getNumberOrDefault(timeout) <= 0) return promise;
59
+ return Promise.race([promise, new Promise((_, reject) => setTimeout(() => reject(new PromiseTimeoutError()), timeout))]);
60
+ }
61
+ var MESSAGE_EXPECTATION = "Timed function expected a Promise";
62
+ var MESSAGE_TIMEOUT = "Promise timed out";
63
+ var NAME = "PromiseTimeoutError";
64
+ var TYPE_FULFILLED = "fulfilled";
65
+ var TYPE_REJECTED = "rejected";
66
+ export { PromiseTimeoutError, delay, promises, timed };
package/dist/queue.js ADDED
@@ -0,0 +1,169 @@
1
+ var Queue = class {
2
+ #callback;
3
+ #handled = [];
4
+ #id = 0;
5
+ #items = [];
6
+ #options;
7
+ #paused;
8
+ #runners = 0;
9
+ /**
10
+ * Is the queue active?
11
+ */
12
+ get active() {
13
+ return this.#runners > 0;
14
+ }
15
+ /**
16
+ * Is the queue empty?
17
+ */
18
+ get empty() {
19
+ return this.#items.length === 0;
20
+ }
21
+ /**
22
+ * Is the queue full?
23
+ */
24
+ get full() {
25
+ return this.#options.maximum > 0 && this.#items.length >= this.#options.maximum;
26
+ }
27
+ /**
28
+ * Is the queue paused?
29
+ */
30
+ get paused() {
31
+ return this.#paused;
32
+ }
33
+ /**
34
+ * Number of items in the queue
35
+ */
36
+ get size() {
37
+ return this.#items.length;
38
+ }
39
+ constructor(callback, options) {
40
+ this.#callback = callback;
41
+ this.#options = options;
42
+ this.#paused = !options.autostart;
43
+ }
44
+ /**
45
+ * Add an item to the queue
46
+ * @param parameters Parameters to use when item runs
47
+ * @returns Queued item
48
+ */
49
+ add(...parameters) {
50
+ if (this.full) throw new QueueError(MESSAGE_MAXIMUM);
51
+ let rejector;
52
+ let resolver;
53
+ const id = this.#identify();
54
+ const promise = new Promise((resolve, reject) => {
55
+ rejector = reject;
56
+ resolver = resolve;
57
+ });
58
+ this.#items.push({
59
+ id,
60
+ parameters,
61
+ promise,
62
+ reject: rejector,
63
+ resolve: resolver
64
+ });
65
+ if (this.#options.autostart) this.#run();
66
+ return {
67
+ id,
68
+ promise
69
+ };
70
+ }
71
+ /**
72
+ * Remove and reject all items in the queue
73
+ */
74
+ clear() {
75
+ const items = this.#items.splice(0);
76
+ const { length } = items;
77
+ for (let index = 0; index < length; index += 1) items[index].reject(new QueueError(MESSAGE_CLEAR));
78
+ }
79
+ /**
80
+ * Pause the queue
81
+ *
82
+ * - Currently running items will not be stopped
83
+ * - New added items will not run until the queue is resumed
84
+ */
85
+ pause() {
86
+ this.#paused = true;
87
+ }
88
+ /**
89
+ * Remove and reject a specific item in the queue
90
+ * @param id ID of queued item
91
+ */
92
+ remove(id) {
93
+ const index = this.#items.findIndex((item) => item.id === id);
94
+ if (index > -1) {
95
+ const [item] = this.#items.splice(index, 1);
96
+ item.reject(new QueueError(MESSAGE_REMOVE));
97
+ }
98
+ }
99
+ /**
100
+ * Resume the queue
101
+ */
102
+ resume() {
103
+ if (this.#paused) {
104
+ const handled = this.#handled.splice(0);
105
+ const { length } = handled;
106
+ for (let index = 0; index < length; index += 1) handled[index]();
107
+ }
108
+ this.#paused = false;
109
+ const length = Math.min(this.#options.concurrency, this.#items.length);
110
+ for (let index = 0; index < length; index += 1) this.#run();
111
+ }
112
+ #identify() {
113
+ this.#id += 1;
114
+ return this.#id;
115
+ }
116
+ async #run() {
117
+ if (this.#paused || this.#runners >= this.#options.concurrency) return;
118
+ this.#runners += 1;
119
+ let item = this.#items.shift();
120
+ while (item != null) {
121
+ let handler;
122
+ let result;
123
+ try {
124
+ result = await this.#callback(...item.parameters);
125
+ handler = item.resolve;
126
+ } catch (thrown) {
127
+ result = thrown;
128
+ handler = item.reject;
129
+ }
130
+ if (this.#paused) {
131
+ this.#handled.push(() => handler(result));
132
+ break;
133
+ }
134
+ handler(result);
135
+ item = this.#items.shift();
136
+ }
137
+ this.#runners -= 1;
138
+ }
139
+ };
140
+ var QueueError = class extends Error {
141
+ constructor(message) {
142
+ super(message);
143
+ this.name = ERROR_NAME;
144
+ }
145
+ };
146
+ function getBooleanOrDefault(value, defaultValue) {
147
+ return typeof value === "boolean" ? value : defaultValue;
148
+ }
149
+ function getNumberOrDefault(value, defaultValue) {
150
+ return typeof value === "number" && value > 0 ? Math.floor(value) : defaultValue;
151
+ }
152
+ function getOptions(input) {
153
+ const options = typeof input === "object" && input != null ? input : {};
154
+ return {
155
+ autostart: getBooleanOrDefault(options.autostart, true),
156
+ concurrency: getNumberOrDefault(options.concurrency, 1),
157
+ maximum: getNumberOrDefault(options.maximum, 0)
158
+ };
159
+ }
160
+ function queue(callback, options) {
161
+ if (typeof callback !== "function") throw new TypeError(MESSAGE_CALLBACK);
162
+ return new Queue(callback, getOptions(options));
163
+ }
164
+ var ERROR_NAME = "QueueError";
165
+ var MESSAGE_CALLBACK = "A Queue requires a callback function";
166
+ var MESSAGE_CLEAR = "Queue was cleared";
167
+ var MESSAGE_MAXIMUM = "Queue has reached its maximum size";
168
+ var MESSAGE_REMOVE = "Item removed from queue";
169
+ export { QueueError, queue };
package/package.json CHANGED
@@ -7,9 +7,9 @@
7
7
  "devDependencies": {
8
8
  "@types/node": "^25.2",
9
9
  "@vitest/coverage-istanbul": "^4",
10
- "jsdom": "^28",
11
- "oxfmt": "^0.31",
12
- "oxlint": "^1.46",
10
+ "jsdom": "^28.1",
11
+ "oxfmt": "^0.33",
12
+ "oxlint": "^1.48",
13
13
  "rolldown": "1.0.0-rc.4",
14
14
  "tslib": "^2.8",
15
15
  "typescript": "^5.9",
@@ -19,75 +19,90 @@
19
19
  "exports": {
20
20
  "./package.json": "./package.json",
21
21
  ".": {
22
- "types": "./types/index.d.ts",
23
- "default": "./dist/index.js"
22
+ "types": "./types/index.d.ts",
23
+ "default": "./dist/index.js"
24
24
  },
25
25
  "./array": {
26
- "types": "./types/array/index.d.ts",
27
- "default": "./dist/array/index.js"
26
+ "types": "./types/array/index.d.ts",
27
+ "default": "./dist/array/index.js"
28
28
  },
29
29
  "./beacon": {
30
- "types": "./types/beacon.d.ts",
31
- "default": "./dist/beacon.js"
30
+ "types": "./types/beacon.d.ts",
31
+ "default": "./dist/beacon.js"
32
32
  },
33
33
  "./color": {
34
- "types": "./types/color/index.d.ts",
35
- "default": "./dist/color/index.js"
34
+ "types": "./types/color/index.d.ts",
35
+ "default": "./dist/color/index.js"
36
36
  },
37
37
  "./frame-rate": {
38
38
  "types": "./types/internal/frame-rate.d.ts",
39
39
  "default": "./dist/internal/frame-rate.js"
40
40
  },
41
41
  "./function": {
42
- "types": "./types/function.d.ts",
43
- "default": "./dist/function.js"
42
+ "types": "./types/function.d.ts",
43
+ "default": "./dist/function.js"
44
44
  },
45
45
  "./is": {
46
- "types": "./types/is.d.ts",
47
- "default": "./dist/is.js"
46
+ "types": "./types/is.d.ts",
47
+ "default": "./dist/is.js"
48
48
  },
49
49
  "./logger": {
50
- "types": "./types/logger.d.ts",
51
- "default": "./dist/logger.js"
50
+ "types": "./types/logger.d.ts",
51
+ "default": "./dist/logger.js"
52
52
  },
53
53
  "./math": {
54
- "types": "./types/math.d.ts",
55
- "default": "./dist/math.js"
54
+ "types": "./types/math.d.ts",
55
+ "default": "./dist/math.js"
56
56
  },
57
57
  "./models": {
58
- "types": "./types/models.d.ts"
58
+ "types": "./types/models.d.ts"
59
59
  },
60
60
  "./number": {
61
- "types": "./types/number.d.ts",
62
- "default": "./dist/number.js"
61
+ "types": "./types/number.d.ts",
62
+ "default": "./dist/number.js"
63
+ },
64
+ "./promise": {
65
+ "types": "./types/promise.d.ts",
66
+ "default": "./dist/promise.js"
67
+ },
68
+ "./queue": {
69
+ "types": "./types/queue.d.ts",
70
+ "default": "./dist/queue.js"
63
71
  },
64
72
  "./query": {
65
- "types": "./types/query.d.ts",
66
- "default": "./dist/query.js"
73
+ "types": "./types/query.d.ts",
74
+ "default": "./dist/query.js"
67
75
  },
68
76
  "./random": {
69
- "types": "./types/random.d.ts",
70
- "default": "./dist/random.js"
77
+ "types": "./types/random.d.ts",
78
+ "default": "./dist/random.js"
71
79
  },
72
80
  "./result": {
73
- "types": "./types/result.d.ts",
74
- "default": "./dist/result.js"
81
+ "types": "./types/result.d.ts",
82
+ "default": "./dist/result.js"
75
83
  },
76
84
  "./sized": {
77
- "types": "./types/sized.d.ts",
78
- "default": "./dist/sized.js"
85
+ "types": "./types/sized.d.ts",
86
+ "default": "./dist/sized.js"
79
87
  },
80
88
  "./string": {
81
- "types": "./types/string/index.d.ts",
82
- "default": "./dist/string/index.js"
89
+ "types": "./types/string/index.d.ts",
90
+ "default": "./dist/string/index.js"
83
91
  },
84
92
  "./value": {
85
- "types": "./types/value/index.d.ts",
86
- "default": "./dist/value/index.js"
93
+ "types": "./types/value/index.d.ts",
94
+ "default": "./dist/value/index.js"
87
95
  }
88
96
  },
89
- "files": ["dist", "src", "types"],
90
- "keywords": ["helper", "utility"],
97
+ "files": [
98
+ "dist",
99
+ "src",
100
+ "types"
101
+ ],
102
+ "keywords": [
103
+ "helper",
104
+ "utility"
105
+ ],
91
106
  "license": "MIT",
92
107
  "module": "./dist/index.js",
93
108
  "name": "@oscarpalmer/atoms",
@@ -105,5 +120,5 @@
105
120
  },
106
121
  "type": "module",
107
122
  "types": "./types/index.d.ts",
108
- "version": "0.131.0"
123
+ "version": "0.133.0"
109
124
  }
package/src/index.ts CHANGED
@@ -9,6 +9,8 @@ export * from './logger';
9
9
  export * from './math';
10
10
  export * from './models';
11
11
  export * from './number';
12
+ export * from './promise';
13
+ export * from './queue';
12
14
  export * from './query';
13
15
  export * from './random';
14
16
  export * from './result';
package/src/models.ts CHANGED
@@ -25,6 +25,11 @@ export type EventPosition = {
25
25
  y: number;
26
26
  };
27
27
 
28
+ /**
29
+ * A generic async callback function
30
+ */
31
+ export type GenericAsyncCallback = (...args: any[]) => Promise<any>;
32
+
28
33
  /**
29
34
  * A generic callback function
30
35
  */
package/src/promise.ts ADDED
@@ -0,0 +1,175 @@
1
+ // #region Types
2
+
3
+ type Data<Items extends unknown[]> = {
4
+ last: number;
5
+ result: Items | PromisesResult<Items>;
6
+ };
7
+
8
+ type Handlers<Items extends unknown[]> = {
9
+ resolve: (value: Items | PromisesResult<Items>) => void;
10
+ reject: (reason: unknown) => void;
11
+ };
12
+
13
+ export class PromiseTimeoutError extends Error {
14
+ constructor() {
15
+ super(MESSAGE_TIMEOUT);
16
+
17
+ this.name = NAME;
18
+ }
19
+ }
20
+
21
+ type Promises<Items extends unknown[]> = {
22
+ [K in keyof Items]: Promise<Items[K]>;
23
+ };
24
+
25
+ type PromisesResult<Items extends unknown[]> = {
26
+ [K in keyof Items]: ResolvedResult<Items[K]> | RejectedResult;
27
+ };
28
+
29
+ type RejectedResult = {
30
+ status: typeof TYPE_REJECTED;
31
+ reason: unknown;
32
+ };
33
+
34
+ type ResolvedResult<Value> = {
35
+ status: typeof TYPE_FULFILLED;
36
+ value: Value;
37
+ };
38
+
39
+ // #endregion
40
+
41
+ // #region Functions
42
+
43
+ /**
44
+ * Create a delayed promise that resolves after a certain amount of time
45
+ * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
46
+ * @returns A promise that resolves after the delay
47
+ */
48
+ export function delay(time?: number): Promise<void> {
49
+ return new Promise(resolve => setTimeout(resolve, getNumberOrDefault(time)));
50
+ }
51
+
52
+ function getBooleanOrDefault(value: unknown, defaultValue: boolean): boolean {
53
+ return typeof value === 'boolean' ? value : defaultValue;
54
+ }
55
+
56
+ function getNumberOrDefault(value: unknown): number {
57
+ return typeof value === 'number' ? value : 0;
58
+ }
59
+
60
+ /**
61
+ * Handle a list of promises, returning their results in an ordered array. If any promise in the list is rejected, the whole function will reject
62
+ * @param items List of promises
63
+ * @param eager Reject immediately if any promise is rejected
64
+ * @return List of results
65
+ */
66
+ export async function promises<Items extends unknown[]>(
67
+ items: Promises<Items>,
68
+ eager: true,
69
+ ): Promise<Items>;
70
+
71
+ /**
72
+ * Handle a list of promises, returning their results in an ordered array of rejected and resolved results
73
+ * @param items List of promises
74
+ * @return List of results
75
+ */
76
+ export async function promises<Items extends unknown[]>(
77
+ items: Promises<Items>,
78
+ ): Promise<PromisesResult<Items>>;
79
+
80
+ export async function promises<Items extends unknown[]>(
81
+ items: Promises<Items>,
82
+ eager?: unknown,
83
+ ): Promise<Items | PromisesResult<Items>> {
84
+ const actual = items.filter(item => item instanceof Promise);
85
+
86
+ if (actual.length === 0) {
87
+ return actual as unknown as Items | PromisesResult<Items>;
88
+ }
89
+
90
+ const isEager = getBooleanOrDefault(eager, false);
91
+
92
+ const {length} = actual;
93
+
94
+ const data: Data<Items> = {
95
+ last: length - 1,
96
+ result: [] as unknown as Items | PromisesResult<Items>,
97
+ };
98
+
99
+ let handlers: Handlers<Items>;
100
+
101
+ return new Promise((resolve, reject) => {
102
+ handlers = {reject, resolve};
103
+
104
+ for (let index = 0; index < length; index += 1) {
105
+ void actual[index]
106
+ .then(value => resolveResult(index, data, handlers, value, isEager))
107
+ .catch(reason => rejectResult(index, data, handlers, reason, isEager));
108
+ }
109
+ });
110
+ }
111
+
112
+ function rejectResult<Items extends unknown[]>(
113
+ index: number,
114
+ data: Data<Items>,
115
+ handlers: Handlers<Items>,
116
+ reason: unknown,
117
+ eager: boolean,
118
+ ) {
119
+ if (eager) {
120
+ handlers.reject(reason);
121
+ } else {
122
+ data.result[index] = {status: TYPE_REJECTED, reason};
123
+
124
+ if (index === data.last) {
125
+ handlers.resolve(data.result as Items | PromisesResult<Items>);
126
+ }
127
+ }
128
+ }
129
+
130
+ function resolveResult<Items extends unknown[]>(
131
+ index: number,
132
+ data: Data<Items>,
133
+ handlers: Handlers<Items>,
134
+ value: unknown,
135
+ eager: boolean,
136
+ ) {
137
+ (data.result as unknown[])[index] = eager ? value : {status: TYPE_FULFILLED, value};
138
+
139
+ if (index === data.last) {
140
+ handlers.resolve(data.result as Items | PromisesResult<Items>);
141
+ }
142
+ }
143
+
144
+ export function timed(promise: Promise<unknown>, timeout: number): Promise<unknown> {
145
+ if (!(promise instanceof Promise)) {
146
+ throw new TypeError(MESSAGE_EXPECTATION);
147
+ }
148
+
149
+ const time = getNumberOrDefault(timeout);
150
+
151
+ if (time <= 0) {
152
+ return promise;
153
+ }
154
+
155
+ return Promise.race([
156
+ promise,
157
+ new Promise((_, reject) => setTimeout(() => reject(new PromiseTimeoutError()), timeout)),
158
+ ]);
159
+ }
160
+
161
+ // #endregion
162
+
163
+ // #region Variables
164
+
165
+ const MESSAGE_EXPECTATION = 'Timed function expected a Promise';
166
+
167
+ const MESSAGE_TIMEOUT = 'Promise timed out';
168
+
169
+ const NAME = 'PromiseTimeoutError';
170
+
171
+ const TYPE_FULFILLED = 'fulfilled';
172
+
173
+ const TYPE_REJECTED = 'rejected';
174
+
175
+ // #endregion
package/src/queue.ts ADDED
@@ -0,0 +1,308 @@
1
+ import type {GenericAsyncCallback, GenericCallback} from './models';
2
+
3
+ // #region Types and classes
4
+
5
+ class Queue<CallbackParameters extends Parameters<GenericAsyncCallback>, CallbackResult> {
6
+ readonly #callback: GenericAsyncCallback;
7
+
8
+ readonly #handled: Array<GenericCallback> = [];
9
+
10
+ #id = 0;
11
+
12
+ readonly #items: Array<QueuedItem<CallbackParameters, CallbackResult>> = [];
13
+
14
+ readonly #options: Required<QueueOptions>;
15
+
16
+ #paused: boolean;
17
+
18
+ #runners = 0;
19
+
20
+ /**
21
+ * Is the queue active?
22
+ */
23
+ get active(): boolean {
24
+ return this.#runners > 0;
25
+ }
26
+
27
+ /**
28
+ * Is the queue empty?
29
+ */
30
+ get empty(): boolean {
31
+ return this.#items.length === 0;
32
+ }
33
+
34
+ /**
35
+ * Is the queue full?
36
+ */
37
+ get full(): boolean {
38
+ return this.#options.maximum > 0 && this.#items.length >= this.#options.maximum;
39
+ }
40
+
41
+ /**
42
+ * Is the queue paused?
43
+ */
44
+ get paused(): boolean {
45
+ return this.#paused;
46
+ }
47
+
48
+ /**
49
+ * Number of items in the queue
50
+ */
51
+ get size(): number {
52
+ return this.#items.length;
53
+ }
54
+
55
+ constructor(callback: GenericAsyncCallback, options: Required<QueueOptions>) {
56
+ this.#callback = callback;
57
+ this.#options = options;
58
+
59
+ this.#paused = !options.autostart;
60
+ }
61
+
62
+ /**
63
+ * Add an item to the queue
64
+ * @param parameters Parameters to use when item runs
65
+ * @returns Queued item
66
+ */
67
+ add(...parameters: CallbackParameters): Queued<CallbackResult> {
68
+ if (this.full) {
69
+ throw new QueueError(MESSAGE_MAXIMUM);
70
+ }
71
+
72
+ let rejector: (reason?: unknown) => void;
73
+ let resolver: (value: CallbackResult) => void;
74
+
75
+ const id = this.#identify();
76
+
77
+ const promise = new Promise<CallbackResult>((resolve, reject) => {
78
+ rejector = reject;
79
+ resolver = resolve;
80
+ });
81
+
82
+ this.#items.push({
83
+ id,
84
+ parameters,
85
+ promise,
86
+ reject: rejector!,
87
+ resolve: resolver!,
88
+ });
89
+
90
+ if (this.#options.autostart) {
91
+ void this.#run();
92
+ }
93
+
94
+ return {id, promise};
95
+ }
96
+
97
+ /**
98
+ * Remove and reject all items in the queue
99
+ */
100
+ clear(): void {
101
+ const items = this.#items.splice(0);
102
+ const {length} = items;
103
+
104
+ for (let index = 0; index < length; index += 1) {
105
+ items[index].reject(new QueueError(MESSAGE_CLEAR));
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Pause the queue
111
+ *
112
+ * - Currently running items will not be stopped
113
+ * - New added items will not run until the queue is resumed
114
+ */
115
+ pause(): void {
116
+ this.#paused = true;
117
+ }
118
+
119
+ /**
120
+ * Remove and reject a specific item in the queue
121
+ * @param id ID of queued item
122
+ */
123
+ remove(id: number): void {
124
+ const index = this.#items.findIndex(item => item.id === id);
125
+
126
+ if (index > -1) {
127
+ const [item] = this.#items.splice(index, 1);
128
+
129
+ item.reject(new QueueError(MESSAGE_REMOVE));
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Resume the queue
135
+ */
136
+ resume(): void {
137
+ if (this.#paused) {
138
+ const handled = this.#handled.splice(0);
139
+ const {length} = handled;
140
+
141
+ for (let index = 0; index < length; index += 1) {
142
+ handled[index]();
143
+ }
144
+ }
145
+
146
+ this.#paused = false;
147
+
148
+ const length = Math.min(this.#options.concurrency, this.#items.length);
149
+
150
+ for (let index = 0; index < length; index += 1) {
151
+ void this.#run();
152
+ }
153
+ }
154
+
155
+ #identify(): number {
156
+ this.#id += 1;
157
+
158
+ return this.#id;
159
+ }
160
+
161
+ async #run(): Promise<void> {
162
+ if (this.#paused || this.#runners >= this.#options.concurrency) {
163
+ return;
164
+ }
165
+
166
+ this.#runners += 1;
167
+
168
+ let item = this.#items.shift();
169
+
170
+ while (item != null) {
171
+ let handler: GenericCallback;
172
+ let result: unknown | CallbackResult;
173
+
174
+ try {
175
+ result = await this.#callback(...item.parameters);
176
+ handler = item.resolve;
177
+ } catch (thrown) {
178
+ result = thrown;
179
+ handler = item.reject;
180
+ }
181
+
182
+ if (this.#paused) {
183
+ this.#handled.push(() => handler(result));
184
+
185
+ break;
186
+ }
187
+
188
+ handler(result);
189
+
190
+ item = this.#items.shift();
191
+ }
192
+
193
+ this.#runners -= 1;
194
+ }
195
+ }
196
+
197
+ class QueueError extends Error {
198
+ constructor(message: string) {
199
+ super(message);
200
+
201
+ this.name = ERROR_NAME;
202
+ }
203
+ }
204
+
205
+ type QueueOptions = {
206
+ /**
207
+ * Automatically start processing the queue when the first item is added _(defaults to `true`)_
208
+ */
209
+ autostart?: boolean;
210
+ /**
211
+ * Number of runners to process the queue concurrently _(defaults to `1`)_
212
+ */
213
+ concurrency?: number;
214
+ /**
215
+ * Maximum number of items allowed in the queue _(defaults to `0`, which means no limit)_
216
+ */
217
+ maximum?: number;
218
+ };
219
+
220
+ type Queued<Value> = {
221
+ readonly id: number;
222
+ readonly promise: Promise<Value>;
223
+ };
224
+
225
+ type QueuedItem<CallbackParameters extends Parameters<GenericAsyncCallback>, CallbackResult> = {
226
+ id: number;
227
+ parameters: CallbackParameters;
228
+ promise: Promise<CallbackResult>;
229
+ reject: (reason?: unknown) => void;
230
+ resolve: (value: CallbackResult) => void;
231
+ };
232
+
233
+ // #endregion
234
+
235
+ // #region Functions
236
+
237
+ function getBooleanOrDefault(value: unknown, defaultValue: boolean): boolean {
238
+ return typeof value === 'boolean' ? value : defaultValue;
239
+ }
240
+
241
+ function getNumberOrDefault(value: unknown, defaultValue: number): number {
242
+ return typeof value === 'number' && value > 0 ? Math.floor(value) : defaultValue;
243
+ }
244
+
245
+ function getOptions(input?: QueueOptions): Required<QueueOptions> {
246
+ const options = typeof input === 'object' && input != null ? input : {};
247
+
248
+ return {
249
+ autostart: getBooleanOrDefault(options.autostart, true),
250
+ concurrency: getNumberOrDefault(options.concurrency, 1),
251
+ maximum: getNumberOrDefault(options.maximum, 0),
252
+ };
253
+ }
254
+
255
+ /**
256
+ * Create a queue for an asynchronous callback function
257
+ * @param callback Callback function for queued items
258
+ * @param options Queue options
259
+ * @returns Queue instance
260
+ */
261
+ function queue<Callback extends GenericAsyncCallback>(
262
+ callback: Callback,
263
+ options?: QueueOptions,
264
+ ): Queue<Parameters<Callback>, Awaited<ReturnType<Callback>>>;
265
+
266
+ /**
267
+ * Create a queue for an asynchronous callback function
268
+ * @param callback Callback function for queued items
269
+ * @param options Queue options
270
+ * @returns Queue instance
271
+ */
272
+ function queue<Callback extends GenericCallback>(
273
+ callback: Callback,
274
+ options?: QueueOptions,
275
+ ): Queue<Parameters<Callback>, ReturnType<Callback>>;
276
+
277
+ function queue(
278
+ callback: GenericCallback,
279
+ options?: QueueOptions,
280
+ ): Queue<Parameters<GenericCallback>, ReturnType<GenericCallback>> {
281
+ if (typeof callback !== 'function') {
282
+ throw new TypeError(MESSAGE_CALLBACK);
283
+ }
284
+
285
+ return new Queue(callback, getOptions(options));
286
+ }
287
+
288
+ // #endregion
289
+
290
+ // #region Variables
291
+
292
+ const ERROR_NAME = 'QueueError';
293
+
294
+ const MESSAGE_CALLBACK = 'A Queue requires a callback function';
295
+
296
+ const MESSAGE_CLEAR = 'Queue was cleared';
297
+
298
+ const MESSAGE_MAXIMUM = 'Queue has reached its maximum size';
299
+
300
+ const MESSAGE_REMOVE = 'Item removed from queue';
301
+
302
+ // #endregion
303
+
304
+ // #region Exports
305
+
306
+ export {queue, QueueError, type Queue, type Queued, type QueueOptions};
307
+
308
+ // #endregion
package/types/index.d.ts CHANGED
@@ -8,6 +8,8 @@ export * from './logger';
8
8
  export * from './math';
9
9
  export * from './models';
10
10
  export * from './number';
11
+ export * from './promise';
12
+ export * from './queue';
11
13
  export * from './query';
12
14
  export * from './random';
13
15
  export * from './result';
package/types/models.d.ts CHANGED
@@ -19,6 +19,10 @@ export type EventPosition = {
19
19
  x: number;
20
20
  y: number;
21
21
  };
22
+ /**
23
+ * A generic async callback function
24
+ */
25
+ export type GenericAsyncCallback = (...args: any[]) => Promise<any>;
22
26
  /**
23
27
  * A generic callback function
24
28
  */
@@ -0,0 +1,40 @@
1
+ export declare class PromiseTimeoutError extends Error {
2
+ constructor();
3
+ }
4
+ type Promises<Items extends unknown[]> = {
5
+ [K in keyof Items]: Promise<Items[K]>;
6
+ };
7
+ type PromisesResult<Items extends unknown[]> = {
8
+ [K in keyof Items]: ResolvedResult<Items[K]> | RejectedResult;
9
+ };
10
+ type RejectedResult = {
11
+ status: typeof TYPE_REJECTED;
12
+ reason: unknown;
13
+ };
14
+ type ResolvedResult<Value> = {
15
+ status: typeof TYPE_FULFILLED;
16
+ value: Value;
17
+ };
18
+ /**
19
+ * Create a delayed promise that resolves after a certain amount of time
20
+ * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
21
+ * @returns A promise that resolves after the delay
22
+ */
23
+ export declare function delay(time?: number): Promise<void>;
24
+ /**
25
+ * Handle a list of promises, returning their results in an ordered array. If any promise in the list is rejected, the whole function will reject
26
+ * @param items List of promises
27
+ * @param eager Reject immediately if any promise is rejected
28
+ * @return List of results
29
+ */
30
+ export declare function promises<Items extends unknown[]>(items: Promises<Items>, eager: true): Promise<Items>;
31
+ /**
32
+ * Handle a list of promises, returning their results in an ordered array of rejected and resolved results
33
+ * @param items List of promises
34
+ * @return List of results
35
+ */
36
+ export declare function promises<Items extends unknown[]>(items: Promises<Items>): Promise<PromisesResult<Items>>;
37
+ export declare function timed(promise: Promise<unknown>, timeout: number): Promise<unknown>;
38
+ declare const TYPE_FULFILLED = "fulfilled";
39
+ declare const TYPE_REJECTED = "rejected";
40
+ export {};
@@ -0,0 +1,87 @@
1
+ import type { GenericAsyncCallback, GenericCallback } from './models';
2
+ declare class Queue<CallbackParameters extends Parameters<GenericAsyncCallback>, CallbackResult> {
3
+ #private;
4
+ /**
5
+ * Is the queue active?
6
+ */
7
+ get active(): boolean;
8
+ /**
9
+ * Is the queue empty?
10
+ */
11
+ get empty(): boolean;
12
+ /**
13
+ * Is the queue full?
14
+ */
15
+ get full(): boolean;
16
+ /**
17
+ * Is the queue paused?
18
+ */
19
+ get paused(): boolean;
20
+ /**
21
+ * Number of items in the queue
22
+ */
23
+ get size(): number;
24
+ constructor(callback: GenericAsyncCallback, options: Required<QueueOptions>);
25
+ /**
26
+ * Add an item to the queue
27
+ * @param parameters Parameters to use when item runs
28
+ * @returns Queued item
29
+ */
30
+ add(...parameters: CallbackParameters): Queued<CallbackResult>;
31
+ /**
32
+ * Remove and reject all items in the queue
33
+ */
34
+ clear(): void;
35
+ /**
36
+ * Pause the queue
37
+ *
38
+ * - Currently running items will not be stopped
39
+ * - New added items will not run until the queue is resumed
40
+ */
41
+ pause(): void;
42
+ /**
43
+ * Remove and reject a specific item in the queue
44
+ * @param id ID of queued item
45
+ */
46
+ remove(id: number): void;
47
+ /**
48
+ * Resume the queue
49
+ */
50
+ resume(): void;
51
+ }
52
+ declare class QueueError extends Error {
53
+ constructor(message: string);
54
+ }
55
+ type QueueOptions = {
56
+ /**
57
+ * Automatically start processing the queue when the first item is added _(defaults to `true`)_
58
+ */
59
+ autostart?: boolean;
60
+ /**
61
+ * Number of runners to process the queue concurrently _(defaults to `1`)_
62
+ */
63
+ concurrency?: number;
64
+ /**
65
+ * Maximum number of items allowed in the queue _(defaults to `0`, which means no limit)_
66
+ */
67
+ maximum?: number;
68
+ };
69
+ type Queued<Value> = {
70
+ readonly id: number;
71
+ readonly promise: Promise<Value>;
72
+ };
73
+ /**
74
+ * Create a queue for an asynchronous callback function
75
+ * @param callback Callback function for queued items
76
+ * @param options Queue options
77
+ * @returns Queue instance
78
+ */
79
+ declare function queue<Callback extends GenericAsyncCallback>(callback: Callback, options?: QueueOptions): Queue<Parameters<Callback>, Awaited<ReturnType<Callback>>>;
80
+ /**
81
+ * Create a queue for an asynchronous callback function
82
+ * @param callback Callback function for queued items
83
+ * @param options Queue options
84
+ * @returns Queue instance
85
+ */
86
+ declare function queue<Callback extends GenericCallback>(callback: Callback, options?: QueueOptions): Queue<Parameters<Callback>, ReturnType<Callback>>;
87
+ export { queue, QueueError, type Queue, type Queued, type QueueOptions };