tiny-essentials 1.3.2 → 1.5.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 (121) hide show
  1. package/dist/TinyBasicsEs.js +45 -22
  2. package/dist/TinyBasicsEs.min.js +1 -1
  3. package/dist/TinyEssentials.js +223 -22
  4. package/dist/TinyEssentials.min.js +1 -1
  5. package/dist/TinyPromiseQueue.js +214 -0
  6. package/dist/TinyPromiseQueue.min.js +1 -0
  7. package/dist/legacy/crypto/decrypt.d.mts +1 -0
  8. package/dist/legacy/crypto/default.d.mts +1 -0
  9. package/dist/legacy/crypto/encrypt.d.mts +1 -0
  10. package/dist/legacy/crypto/index.d.mts +1 -0
  11. package/dist/legacy/firebase/cookieSession.d.mts +1 -0
  12. package/dist/legacy/firebase/database/index.d.mts +1 -0
  13. package/dist/legacy/firebase/database/presence.d.mts +1 -0
  14. package/dist/legacy/firebase/database/saveAsync.d.mts +1 -0
  15. package/dist/legacy/firebase/databaseEscape.d.mts +1 -0
  16. package/dist/legacy/firebase/databaseLogger.d.mts +1 -0
  17. package/dist/legacy/firebase/discord/api/addGuildMember.d.mts +1 -0
  18. package/dist/legacy/firebase/discord/api/getGuildWidget.d.mts +1 -0
  19. package/dist/legacy/firebase/discord/api/getToken.d.mts +1 -0
  20. package/dist/legacy/firebase/discord/api/getUser.d.mts +1 -0
  21. package/dist/legacy/firebase/discord/api/getUserConnections.d.mts +1 -0
  22. package/dist/legacy/firebase/discord/api/getUserGuilds.d.mts +1 -0
  23. package/dist/legacy/firebase/discord/api/index.d.mts +1 -0
  24. package/dist/legacy/firebase/discord/api/refreshToken.d.mts +1 -0
  25. package/dist/legacy/firebase/discord/api/revokeToken.d.mts +1 -0
  26. package/dist/legacy/firebase/discord/config.d.mts +1 -0
  27. package/dist/legacy/firebase/discord/firebase_redirect/index.d.mts +1 -0
  28. package/dist/legacy/firebase/discord/firebase_redirect/login.d.mts +1 -0
  29. package/dist/legacy/firebase/discord/firebase_redirect/logout.d.mts +1 -0
  30. package/dist/legacy/firebase/discord/get/authURLGenerator.d.mts +1 -0
  31. package/dist/legacy/firebase/discord/get/cookie-session.d.mts +1 -0
  32. package/dist/legacy/firebase/discord/get/credentials.d.mts +1 -0
  33. package/dist/legacy/firebase/discord/get/errorValidator.d.mts +1 -0
  34. package/dist/legacy/firebase/discord/get/index.d.mts +1 -0
  35. package/dist/legacy/firebase/discord/get/randomAvatar.d.mts +1 -0
  36. package/dist/legacy/firebase/discord/http/index.d.mts +1 -0
  37. package/dist/legacy/firebase/discord/http/login.d.mts +1 -0
  38. package/dist/legacy/firebase/discord/http/logout.d.mts +1 -0
  39. package/dist/legacy/firebase/discord/http/redirect.d.mts +1 -0
  40. package/dist/legacy/firebase/discord/http/refreshToken.d.mts +1 -0
  41. package/dist/legacy/firebase/discord/index.d.mts +1 -0
  42. package/dist/legacy/firebase/discord/template/cookie-session.d.mts +1 -0
  43. package/dist/legacy/firebase/domainRedirect.d.mts +1 -0
  44. package/dist/legacy/firebase/escape.d.mts +1 -0
  45. package/dist/legacy/firebase/getDBAsync.d.mts +1 -0
  46. package/dist/legacy/firebase/getDBData.d.mts +1 -0
  47. package/dist/legacy/firebase/getDBValue.d.mts +1 -0
  48. package/dist/legacy/firebase/index.d.mts +1 -0
  49. package/dist/legacy/firebase/isEmulator.d.mts +1 -0
  50. package/dist/legacy/firebase/logger.d.mts +1 -0
  51. package/dist/legacy/firebase/mySQL.d.mts +1 -0
  52. package/dist/legacy/firebase/mysqlConnector/create.d.mts +1 -0
  53. package/dist/legacy/firebase/mysqlConnector/index.d.mts +1 -0
  54. package/dist/legacy/firebase/mysqlConnector/nextPrev.d.mts +1 -0
  55. package/dist/legacy/firebase/mysqlConnector/pagination.d.mts +1 -0
  56. package/dist/legacy/firebase/mysqlConnector/sameUser.d.mts +1 -0
  57. package/dist/legacy/firebase/transactionDBAsync.d.mts +1 -0
  58. package/dist/legacy/get/countObj.d.mts +1 -0
  59. package/dist/legacy/get/decimalColor.d.mts +1 -0
  60. package/dist/legacy/get/objType.d.mts +1 -0
  61. package/dist/legacy/get/pagination.d.mts +1 -0
  62. package/dist/legacy/get/queryUrlByName.d.mts +1 -0
  63. package/dist/legacy/get/queryUrlJSON.d.mts +1 -0
  64. package/dist/legacy/get/super_string_filter.d.mts +1 -0
  65. package/dist/legacy/get/versionCheck.d.mts +1 -0
  66. package/dist/legacy/http/HTTP-1.0.d.mts +1 -0
  67. package/dist/legacy/http/auth.d.mts +1 -0
  68. package/dist/legacy/http/check_domain.d.mts +1 -0
  69. package/dist/legacy/http/csrfTokenAnalyze.d.mts +1 -0
  70. package/dist/legacy/http/domainValidator.d.mts +1 -0
  71. package/dist/legacy/http/errorsCallback.d.mts +1 -0
  72. package/dist/legacy/http/fetch/json.d.mts +1 -0
  73. package/dist/legacy/http/fetch/text.d.mts +1 -0
  74. package/dist/legacy/http/fileCache.d.mts +1 -0
  75. package/dist/legacy/http/getDomainURL.d.mts +1 -0
  76. package/dist/legacy/http/userIP.d.mts +1 -0
  77. package/dist/legacy/index.d.mts +1 -0
  78. package/dist/legacy/libs/arraySortPositions.d.mts +1 -0
  79. package/dist/legacy/libs/capitalize.d.mts +1 -0
  80. package/dist/legacy/libs/convertBytes.d.mts +1 -0
  81. package/dist/legacy/libs/custom_module_loader.d.mts +1 -0
  82. package/dist/legacy/libs/dice.d.mts +1 -0
  83. package/dist/legacy/libs/markdown.d.mts +1 -0
  84. package/dist/legacy/libs/percentage.d.mts +1 -0
  85. package/dist/legacy/libs/regex/getLetter.d.mts +1 -0
  86. package/dist/legacy/libs/replaceAsync.d.mts +1 -0
  87. package/dist/legacy/libs/rule3.d.mts +1 -0
  88. package/dist/legacy/libs/userLevel.d.mts +1 -0
  89. package/dist/legacy/momentjs/getAge.d.mts +1 -0
  90. package/dist/legacy/momentjs/index.d.mts +1 -0
  91. package/dist/legacy/momentjs/timeDuration.d.mts +1 -0
  92. package/dist/legacy/socket.io/antiFlood/index.d.mts +1 -0
  93. package/dist/legacy/socket.io/antiFlood/install.d.mts +1 -0
  94. package/dist/legacy/socket.io/antiFlood/verify.d.mts +1 -0
  95. package/dist/legacy/socket.io/cookie-session.d.mts +1 -0
  96. package/dist/legacy/socket.io/discord.d.mts +1 -0
  97. package/dist/legacy/socket.io/index.d.mts +1 -0
  98. package/dist/v1/basics/array.d.mts +1 -0
  99. package/dist/v1/basics/clock.d.mts +1 -0
  100. package/dist/v1/basics/index.d.mts +1 -0
  101. package/dist/v1/basics/objFilter.cjs +46 -22
  102. package/dist/v1/basics/objFilter.d.mts +13 -2
  103. package/dist/v1/basics/objFilter.mjs +43 -22
  104. package/dist/v1/basics/simpleMath.d.mts +1 -0
  105. package/dist/v1/basics/text.d.mts +1 -0
  106. package/dist/v1/build/TinyLevelUp.d.mts +1 -0
  107. package/dist/v1/build/TinyPromiseQueue.cjs +7 -0
  108. package/dist/v1/build/TinyPromiseQueue.d.mts +3 -0
  109. package/dist/v1/build/TinyPromiseQueue.mjs +2 -0
  110. package/dist/v1/index.cjs +3 -0
  111. package/dist/v1/index.d.mts +4 -1
  112. package/dist/v1/index.mjs +3 -2
  113. package/dist/v1/libs/TinyPromiseQueue.cjs +175 -0
  114. package/dist/v1/libs/TinyPromiseQueue.d.mts +63 -0
  115. package/dist/v1/libs/TinyPromiseQueue.mjs +159 -0
  116. package/docs/README.md +5 -0
  117. package/docs/basics/asyncReplace.md +39 -0
  118. package/docs/basics/objFilter.md +33 -0
  119. package/docs/libs/TinyLevelUp.md +108 -0
  120. package/docs/libs/TinyPromiseQueue.md +126 -0
  121. package/package.json +4 -2
@@ -19,45 +19,45 @@ import { Buffer } from 'buffer';
19
19
  */
20
20
  const typeValidator = {
21
21
  items: {
22
- /** Checks if the value is undefined. */
22
+ /** @param {*} val @returns {val is undefined} */
23
23
  undefined: (val) => typeof val === 'undefined',
24
- /** Checks if the value is null. */
24
+ /** @param {*} val @returns {val is null} */
25
25
  null: (val) => val === null,
26
- /** Checks if the value is a boolean. */
26
+ /** @param {*} val @returns {val is boolean} */
27
27
  boolean: (val) => typeof val === 'boolean',
28
- /** Checks if the value is a number. */
28
+ /** @param {*} val @returns {val is number} */
29
29
  number: (val) => typeof val === 'number' && !isNaN(val),
30
- /** Checks if the value is a bigint. */
30
+ /** @param {*} val @returns {val is bigint} */
31
31
  bigint: (val) => typeof val === 'bigint',
32
- /** Checks if the value is a string. */
32
+ /** @param {*} val @returns {val is string} */
33
33
  string: (val) => typeof val === 'string',
34
- /** Checks if the value is a symbol. */
34
+ /** @param {*} val @returns {val is symbol} */
35
35
  symbol: (val) => typeof val === 'symbol',
36
- /** Checks if the value is a function. */
36
+ /** @param {*} val @returns {val is Function} */
37
37
  function: (val) => typeof val === 'function',
38
- /** Checks if the value is an array. */
38
+ /** @param {*} val @returns {val is Array<any>} */
39
39
  array: (val) => Array.isArray(val),
40
- /** Checks if the value is a Date object. */
40
+ /** @param {*} val @returns {val is Date} */
41
41
  date: (val) => val instanceof Date,
42
- /** Checks if the value is a regular expression. */
42
+ /** @param {*} val @returns {val is RegExp} */
43
43
  regexp: (val) => val instanceof RegExp,
44
- /** Checks if the value is a Map. */
44
+ /** @param {*} val @returns {val is Map<any, any>} */
45
45
  map: (val) => val instanceof Map,
46
- /** Checks if the value is a Set. */
46
+ /** @param {*} val @returns {val is Set<any>} */
47
47
  set: (val) => val instanceof Set,
48
- /** Checks if the value is a WeakMap. */
48
+ /** @param {*} val @returns {val is WeakMap<object, any>} */
49
49
  weakmap: (val) => val instanceof WeakMap,
50
- /** Checks if the value is a WeakSet. */
50
+ /** @param {*} val @returns {val is WeakSet<object>} */
51
51
  weakset: (val) => val instanceof WeakSet,
52
- /** Checks if the value is a Promise. */
52
+ /** @param {*} val @returns {val is Promise<any>} */
53
53
  promise: (val) => val instanceof Promise,
54
- /** Checks if the value is a Buffer. */
54
+ /** @param {*} val @returns {val is Buffer} */
55
55
  buffer: (val) => typeof Buffer !== 'undefined' && Buffer.isBuffer(val),
56
- /** Checks if the value is a File. */
56
+ /** @param {*} val @returns {val is File} */
57
57
  file: (val) => typeof File !== 'undefined' && val instanceof File,
58
- /** Checks if the value is a Html Element. */
58
+ /** @param {*} val @returns {val is HTMLElement} */
59
59
  htmlelement: (val) => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement,
60
- /** Checks if the value is a non-null plain object or instance of a class. */
60
+ /** @param {*} val @returns {val is object} */
61
61
  object: (val) => typeof val === 'object' && val !== null,
62
62
  },
63
63
  /** Evaluation order of the type checkers. */
@@ -172,7 +172,7 @@ const getType = (val) => {
172
172
  if (val === null)
173
173
  return 'null';
174
174
  for (const name of typeValidator.order)
175
- if (!typeValidator.items[name] || typeValidator.items[name](val))
175
+ if (typeof typeValidator.items[name] !== 'function' || typeValidator.items[name](val))
176
176
  return name;
177
177
  return 'unknown';
178
178
  };
@@ -198,10 +198,31 @@ export function objType(obj, type) {
198
198
  return result === type.toLowerCase();
199
199
  return result;
200
200
  }
201
+ /**
202
+ * Checks the type of a given object and returns the validation value if a known type is detected.
203
+ *
204
+ * @param {*} obj - The object to check or identify.
205
+ * @returns {{ valid:*; type: string | null }} - Returns the type result.
206
+ */
207
+ export function checkObj(obj) {
208
+ /** @type {{ valid:*; type: string | null }} */
209
+ const data = { valid: null, type: null };
210
+ for (const name of typeValidator.order) {
211
+ if (typeof typeValidator.items[name] === 'function') {
212
+ const result = typeValidator.items[name](obj);
213
+ if (result) {
214
+ data.valid = result;
215
+ data.type = name;
216
+ break;
217
+ }
218
+ }
219
+ }
220
+ return data;
221
+ }
201
222
  /**
202
223
  * Counts the number of elements in an array or the number of properties in an object.
203
224
  *
204
- * @param {*} obj - The array or object to count.
225
+ * @param {Array<*>|Record<string|number, any>} obj - The array or object to count.
205
226
  * @returns {number} - The count of items (array elements or object keys), or `0` if the input is neither an array nor an object.
206
227
  *
207
228
  * @example
@@ -52,3 +52,4 @@ export function getSimplePerc(price: number, percentage: number): number;
52
52
  * @returns {number|null} The age in years, or null if `timeData` is not provided or invalid.
53
53
  */
54
54
  export function getAge(timeData?: number | string | Date, now?: Date | null): number | null;
55
+ //# sourceMappingURL=simpleMath.d.mts.map
@@ -18,3 +18,4 @@ export function toTitleCase(str: string): string;
18
18
  * @returns {string} The string converted to title case with the first letter in lowercase.
19
19
  */
20
20
  export function toTitleCaseLowerFirst(str: string): string;
21
+ //# sourceMappingURL=text.d.mts.map
@@ -1,2 +1,3 @@
1
1
  export { TinyLevelUp };
2
2
  import TinyLevelUp from '../../legacy/libs/userLevel.mjs';
3
+ //# sourceMappingURL=TinyLevelUp.d.mts.map
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ var TinyPromiseQueue = require('../libs/TinyPromiseQueue.cjs');
4
+
5
+
6
+
7
+ exports.TinyPromiseQueue = TinyPromiseQueue;
@@ -0,0 +1,3 @@
1
+ export { TinyPromiseQueue };
2
+ import TinyPromiseQueue from '../libs/TinyPromiseQueue.mjs';
3
+ //# sourceMappingURL=TinyPromiseQueue.d.mts.map
@@ -0,0 +1,2 @@
1
+ import TinyPromiseQueue from '../libs/TinyPromiseQueue.mjs';
2
+ export { TinyPromiseQueue };
package/dist/v1/index.cjs CHANGED
@@ -7,6 +7,7 @@ var clock = require('./basics/clock.cjs');
7
7
  var objFilter = require('./basics/objFilter.cjs');
8
8
  var simpleMath = require('./basics/simpleMath.cjs');
9
9
  var text = require('./basics/text.cjs');
10
+ var TinyPromiseQueue = require('./libs/TinyPromiseQueue.cjs');
10
11
 
11
12
 
12
13
 
@@ -17,6 +18,7 @@ exports.formatCustomTimer = clock.formatCustomTimer;
17
18
  exports.formatDayTimer = clock.formatDayTimer;
18
19
  exports.formatTimer = clock.formatTimer;
19
20
  exports.getTimeDuration = clock.getTimeDuration;
21
+ exports.checkObj = objFilter.checkObj;
20
22
  exports.cloneObjTypeOrder = objFilter.cloneObjTypeOrder;
21
23
  exports.countObj = objFilter.countObj;
22
24
  exports.extendObjType = objFilter.extendObjType;
@@ -27,3 +29,4 @@ exports.getSimplePerc = simpleMath.getSimplePerc;
27
29
  exports.ruleOfThree = simpleMath.ruleOfThree;
28
30
  exports.toTitleCase = text.toTitleCase;
29
31
  exports.toTitleCaseLowerFirst = text.toTitleCaseLowerFirst;
32
+ exports.TinyPromiseQueue = TinyPromiseQueue;
@@ -1,8 +1,10 @@
1
+ import TinyPromiseQueue from './libs/TinyPromiseQueue.mjs';
1
2
  import TinyLevelUp from '../legacy/libs/userLevel.mjs';
2
3
  import { extendObjType } from './basics/objFilter.mjs';
3
4
  import { reorderObjTypeOrder } from './basics/objFilter.mjs';
4
5
  import { cloneObjTypeOrder } from './basics/objFilter.mjs';
5
6
  import { countObj } from './basics/objFilter.mjs';
7
+ import { checkObj } from './basics/objFilter.mjs';
6
8
  import { objType } from './basics/objFilter.mjs';
7
9
  import { ruleOfThree } from './basics/simpleMath.mjs';
8
10
  import { getSimplePerc } from './basics/simpleMath.mjs';
@@ -15,4 +17,5 @@ import { getTimeDuration } from './basics/clock.mjs';
15
17
  import { shuffleArray } from './basics/array.mjs';
16
18
  import { toTitleCase } from './basics/text.mjs';
17
19
  import { toTitleCaseLowerFirst } from './basics/text.mjs';
18
- export { TinyLevelUp, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
20
+ export { TinyPromiseQueue, TinyLevelUp, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
21
+ //# sourceMappingURL=index.d.mts.map
package/dist/v1/index.mjs CHANGED
@@ -2,7 +2,8 @@ import asyncReplace from '../legacy/libs/replaceAsync.mjs';
2
2
  import TinyLevelUp from '../legacy/libs/userLevel.mjs';
3
3
  import { shuffleArray } from './basics/array.mjs';
4
4
  import { formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, } from './basics/clock.mjs';
5
- import { countObj, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, objType, } from './basics/objFilter.mjs';
5
+ import { countObj, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, objType, checkObj, } from './basics/objFilter.mjs';
6
6
  import { getAge, getSimplePerc, ruleOfThree } from './basics/simpleMath.mjs';
7
7
  import { toTitleCase, toTitleCaseLowerFirst } from './basics/text.mjs';
8
- export { TinyLevelUp, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst, };
8
+ import TinyPromiseQueue from './libs/TinyPromiseQueue.mjs';
9
+ export { TinyPromiseQueue, TinyLevelUp, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst, };
@@ -0,0 +1,175 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * A queue system for managing and executing asynchronous tasks sequentially, one at a time.
5
+ *
6
+ * Tasks can be delayed, reordered, canceled, and processed in strict order. The queue ensures that each task
7
+ * is executed after the previous one finishes, and any task can be skipped or canceled if needed.
8
+ *
9
+ * @class
10
+ */
11
+ class TinyPromiseQueue {
12
+ /**
13
+ * @typedef {Object} QueuedTask
14
+ * @property {() => Promise<any>} task - The async task to execute.
15
+ * @property {(value: any) => any} resolve - The resolve function from the Promise.
16
+ * @property {(reason?: any) => any} reject - The reject function from the Promise.
17
+ * @property {string|undefined} [id] - Optional identifier for the task.
18
+ * @property {number|null|undefined} [delay] - Optional delay (in ms) before the task is executed.
19
+ */
20
+
21
+ /** @type {Array<QueuedTask>} */
22
+ #queue = [];
23
+ #running = false;
24
+ /** @type {Record<string, *>} */
25
+ #timeouts = {};
26
+ /** @type {Set<string>} */
27
+ #blacklist = new Set();
28
+
29
+ /**
30
+ * Returns whether the queue is currently processing a task.
31
+ *
32
+ * @returns {boolean}
33
+ */
34
+ isRunning() {
35
+ return this.#running;
36
+ }
37
+
38
+ /**
39
+ * Processes the next task in the queue if not already running.
40
+ * Ensures tasks are executed in order, one at a time.
41
+ *
42
+ * @returns {Promise<void>}
43
+ */
44
+ async #processQueue() {
45
+ if (this.#running || this.#queue.length === 0) return;
46
+ this.#running = true;
47
+ const data = this.#queue.shift();
48
+ if (
49
+ data &&
50
+ typeof data.task === 'function' &&
51
+ typeof data.resolve === 'function' &&
52
+ typeof data.reject === 'function'
53
+ ) {
54
+ const { task, resolve, reject, delay, id } = data;
55
+ try {
56
+ if (delay && id) {
57
+ await new Promise((resolveDelay) => {
58
+ const timeoutId = setTimeout(() => {
59
+ delete this.#timeouts[id];
60
+ resolveDelay(null);
61
+ }, delay);
62
+ this.#timeouts[id] = timeoutId;
63
+ });
64
+ }
65
+
66
+ if (id && this.#blacklist.has(id)) {
67
+ reject(new Error('The function was canceled on TinyPromiseQueue.'));
68
+ this.#blacklist.delete(id);
69
+ this.#running = false;
70
+ this.#processQueue();
71
+ return;
72
+ }
73
+
74
+ const result = await task();
75
+ resolve(result);
76
+ } catch (error) {
77
+ reject(error);
78
+ } finally {
79
+ this.#running = false;
80
+ this.#processQueue();
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Returns the index of a task by its ID.
87
+ *
88
+ * @param {string} id The ID of the task to locate.
89
+ * @returns {number} The index of the task in the queue, or -1 if not found.
90
+ */
91
+ getIndexById(id) {
92
+ return this.#queue.findIndex((item) => item.id === id);
93
+ }
94
+
95
+ /**
96
+ * Returns a list of IDs for all tasks currently in the queue.
97
+ *
98
+ * @returns {{ index: number, id: string }[]} An array of task IDs currently queued.
99
+ */
100
+ getQueuedIds() {
101
+ // @ts-ignore
102
+ return this.#queue
103
+ .map((item, index) => ({ index, id: item.id }))
104
+ .filter((entry) => typeof entry.id === 'string');
105
+ }
106
+
107
+ /**
108
+ * Reorders a task in the queue from one index to another.
109
+ *
110
+ * @param {number} fromIndex The current index of the task to move.
111
+ * @param {number} toIndex The index where the task should be placed.
112
+ */
113
+ reorderQueue(fromIndex, toIndex) {
114
+ if (
115
+ typeof fromIndex !== 'number' ||
116
+ typeof toIndex !== 'number' ||
117
+ fromIndex < 0 ||
118
+ toIndex < 0 ||
119
+ fromIndex >= this.#queue.length ||
120
+ toIndex >= this.#queue.length
121
+ )
122
+ return;
123
+ const [item] = this.#queue.splice(fromIndex, 1);
124
+ this.#queue.splice(toIndex, 0, item);
125
+ }
126
+
127
+ /**
128
+ * Adds a new async task to the queue and ensures it runs in order after previous tasks.
129
+ * Optionally, a delay can be added before the task is executed.
130
+ *
131
+ * If the task is canceled before execution, it will be rejected with the message:
132
+ * "The function was canceled on TinyPromiseQueue."
133
+ *
134
+ * @param {(...args: any[]) => Promise<any>} task A function that returns a Promise to be executed sequentially.
135
+ * @param {number|null} [delay] Optional delay (in ms) before the task is executed.
136
+ * @param {string} [id] Optional ID to identify the task in the queue.
137
+ * @returns {Promise<any>} A Promise that resolves or rejects with the result of the task once it's processed.
138
+ */
139
+ enqueue(task, delay, id) {
140
+ return new Promise((resolve, reject) => {
141
+ this.#queue.push({ task, resolve, reject, id, delay });
142
+ this.#processQueue();
143
+ });
144
+ }
145
+
146
+ /**
147
+ * Cancels a scheduled delay and removes the task from the queue.
148
+ * Adds the ID to a blacklist so the task is skipped if already being processed.
149
+ *
150
+ * @param {string} id The ID of the task to cancel.
151
+ * @returns {boolean} True if a delay was cancelled and the task was removed.
152
+ */
153
+ cancelTask(id) {
154
+ if (!id) return false;
155
+ let cancelled = false;
156
+
157
+ if (id in this.#timeouts) {
158
+ clearTimeout(this.#timeouts[id]);
159
+ delete this.#timeouts[id];
160
+ cancelled = true;
161
+ }
162
+
163
+ const index = this.getIndexById(id);
164
+ if (index !== -1) {
165
+ this.#queue.splice(index, 1);
166
+ cancelled = true;
167
+ }
168
+
169
+ if (cancelled) this.#blacklist.add(id);
170
+
171
+ return cancelled;
172
+ }
173
+ }
174
+
175
+ module.exports = TinyPromiseQueue;
@@ -0,0 +1,63 @@
1
+ export default TinyPromiseQueue;
2
+ /**
3
+ * A queue system for managing and executing asynchronous tasks sequentially, one at a time.
4
+ *
5
+ * Tasks can be delayed, reordered, canceled, and processed in strict order. The queue ensures that each task
6
+ * is executed after the previous one finishes, and any task can be skipped or canceled if needed.
7
+ *
8
+ * @class
9
+ */
10
+ declare class TinyPromiseQueue {
11
+ /**
12
+ * Returns whether the queue is currently processing a task.
13
+ *
14
+ * @returns {boolean}
15
+ */
16
+ isRunning(): boolean;
17
+ /**
18
+ * Returns the index of a task by its ID.
19
+ *
20
+ * @param {string} id The ID of the task to locate.
21
+ * @returns {number} The index of the task in the queue, or -1 if not found.
22
+ */
23
+ getIndexById(id: string): number;
24
+ /**
25
+ * Returns a list of IDs for all tasks currently in the queue.
26
+ *
27
+ * @returns {{ index: number, id: string }[]} An array of task IDs currently queued.
28
+ */
29
+ getQueuedIds(): {
30
+ index: number;
31
+ id: string;
32
+ }[];
33
+ /**
34
+ * Reorders a task in the queue from one index to another.
35
+ *
36
+ * @param {number} fromIndex The current index of the task to move.
37
+ * @param {number} toIndex The index where the task should be placed.
38
+ */
39
+ reorderQueue(fromIndex: number, toIndex: number): void;
40
+ /**
41
+ * Adds a new async task to the queue and ensures it runs in order after previous tasks.
42
+ * Optionally, a delay can be added before the task is executed.
43
+ *
44
+ * If the task is canceled before execution, it will be rejected with the message:
45
+ * "The function was canceled on TinyPromiseQueue."
46
+ *
47
+ * @param {(...args: any[]) => Promise<any>} task A function that returns a Promise to be executed sequentially.
48
+ * @param {number|null} [delay] Optional delay (in ms) before the task is executed.
49
+ * @param {string} [id] Optional ID to identify the task in the queue.
50
+ * @returns {Promise<any>} A Promise that resolves or rejects with the result of the task once it's processed.
51
+ */
52
+ enqueue(task: (...args: any[]) => Promise<any>, delay?: number | null, id?: string): Promise<any>;
53
+ /**
54
+ * Cancels a scheduled delay and removes the task from the queue.
55
+ * Adds the ID to a blacklist so the task is skipped if already being processed.
56
+ *
57
+ * @param {string} id The ID of the task to cancel.
58
+ * @returns {boolean} True if a delay was cancelled and the task was removed.
59
+ */
60
+ cancelTask(id: string): boolean;
61
+ #private;
62
+ }
63
+ //# sourceMappingURL=TinyPromiseQueue.d.mts.map
@@ -0,0 +1,159 @@
1
+ /**
2
+ * A queue system for managing and executing asynchronous tasks sequentially, one at a time.
3
+ *
4
+ * Tasks can be delayed, reordered, canceled, and processed in strict order. The queue ensures that each task
5
+ * is executed after the previous one finishes, and any task can be skipped or canceled if needed.
6
+ *
7
+ * @class
8
+ */
9
+ class TinyPromiseQueue {
10
+ /**
11
+ * @typedef {Object} QueuedTask
12
+ * @property {() => Promise<any>} task - The async task to execute.
13
+ * @property {(value: any) => any} resolve - The resolve function from the Promise.
14
+ * @property {(reason?: any) => any} reject - The reject function from the Promise.
15
+ * @property {string|undefined} [id] - Optional identifier for the task.
16
+ * @property {number|null|undefined} [delay] - Optional delay (in ms) before the task is executed.
17
+ */
18
+ /** @type {Array<QueuedTask>} */
19
+ #queue = [];
20
+ #running = false;
21
+ /** @type {Record<string, *>} */
22
+ #timeouts = {};
23
+ /** @type {Set<string>} */
24
+ #blacklist = new Set();
25
+ /**
26
+ * Returns whether the queue is currently processing a task.
27
+ *
28
+ * @returns {boolean}
29
+ */
30
+ isRunning() {
31
+ return this.#running;
32
+ }
33
+ /**
34
+ * Processes the next task in the queue if not already running.
35
+ * Ensures tasks are executed in order, one at a time.
36
+ *
37
+ * @returns {Promise<void>}
38
+ */
39
+ async #processQueue() {
40
+ if (this.#running || this.#queue.length === 0)
41
+ return;
42
+ this.#running = true;
43
+ const data = this.#queue.shift();
44
+ if (data &&
45
+ typeof data.task === 'function' &&
46
+ typeof data.resolve === 'function' &&
47
+ typeof data.reject === 'function') {
48
+ const { task, resolve, reject, delay, id } = data;
49
+ try {
50
+ if (delay && id) {
51
+ await new Promise((resolveDelay) => {
52
+ const timeoutId = setTimeout(() => {
53
+ delete this.#timeouts[id];
54
+ resolveDelay(null);
55
+ }, delay);
56
+ this.#timeouts[id] = timeoutId;
57
+ });
58
+ }
59
+ if (id && this.#blacklist.has(id)) {
60
+ reject(new Error('The function was canceled on TinyPromiseQueue.'));
61
+ this.#blacklist.delete(id);
62
+ this.#running = false;
63
+ this.#processQueue();
64
+ return;
65
+ }
66
+ const result = await task();
67
+ resolve(result);
68
+ }
69
+ catch (error) {
70
+ reject(error);
71
+ }
72
+ finally {
73
+ this.#running = false;
74
+ this.#processQueue();
75
+ }
76
+ }
77
+ }
78
+ /**
79
+ * Returns the index of a task by its ID.
80
+ *
81
+ * @param {string} id The ID of the task to locate.
82
+ * @returns {number} The index of the task in the queue, or -1 if not found.
83
+ */
84
+ getIndexById(id) {
85
+ return this.#queue.findIndex((item) => item.id === id);
86
+ }
87
+ /**
88
+ * Returns a list of IDs for all tasks currently in the queue.
89
+ *
90
+ * @returns {{ index: number, id: string }[]} An array of task IDs currently queued.
91
+ */
92
+ getQueuedIds() {
93
+ // @ts-ignore
94
+ return this.#queue
95
+ .map((item, index) => ({ index, id: item.id }))
96
+ .filter((entry) => typeof entry.id === 'string');
97
+ }
98
+ /**
99
+ * Reorders a task in the queue from one index to another.
100
+ *
101
+ * @param {number} fromIndex The current index of the task to move.
102
+ * @param {number} toIndex The index where the task should be placed.
103
+ */
104
+ reorderQueue(fromIndex, toIndex) {
105
+ if (typeof fromIndex !== 'number' ||
106
+ typeof toIndex !== 'number' ||
107
+ fromIndex < 0 ||
108
+ toIndex < 0 ||
109
+ fromIndex >= this.#queue.length ||
110
+ toIndex >= this.#queue.length)
111
+ return;
112
+ const [item] = this.#queue.splice(fromIndex, 1);
113
+ this.#queue.splice(toIndex, 0, item);
114
+ }
115
+ /**
116
+ * Adds a new async task to the queue and ensures it runs in order after previous tasks.
117
+ * Optionally, a delay can be added before the task is executed.
118
+ *
119
+ * If the task is canceled before execution, it will be rejected with the message:
120
+ * "The function was canceled on TinyPromiseQueue."
121
+ *
122
+ * @param {(...args: any[]) => Promise<any>} task A function that returns a Promise to be executed sequentially.
123
+ * @param {number|null} [delay] Optional delay (in ms) before the task is executed.
124
+ * @param {string} [id] Optional ID to identify the task in the queue.
125
+ * @returns {Promise<any>} A Promise that resolves or rejects with the result of the task once it's processed.
126
+ */
127
+ enqueue(task, delay, id) {
128
+ return new Promise((resolve, reject) => {
129
+ this.#queue.push({ task, resolve, reject, id, delay });
130
+ this.#processQueue();
131
+ });
132
+ }
133
+ /**
134
+ * Cancels a scheduled delay and removes the task from the queue.
135
+ * Adds the ID to a blacklist so the task is skipped if already being processed.
136
+ *
137
+ * @param {string} id The ID of the task to cancel.
138
+ * @returns {boolean} True if a delay was cancelled and the task was removed.
139
+ */
140
+ cancelTask(id) {
141
+ if (!id)
142
+ return false;
143
+ let cancelled = false;
144
+ if (id in this.#timeouts) {
145
+ clearTimeout(this.#timeouts[id]);
146
+ delete this.#timeouts[id];
147
+ cancelled = true;
148
+ }
149
+ const index = this.getIndexById(id);
150
+ if (index !== -1) {
151
+ this.#queue.splice(index, 1);
152
+ cancelled = true;
153
+ }
154
+ if (cancelled)
155
+ this.#blacklist.add(id);
156
+ return cancelled;
157
+ }
158
+ }
159
+ export default TinyPromiseQueue;
package/docs/README.md CHANGED
@@ -17,6 +17,11 @@ This folder contains the core scripts we have worked on so far. Each file is a m
17
17
  - 🧠 **[objFilter.md](./basics/objFilter.md)** — Type detection, extension, and analysis made easy with simple and extensible type validation.
18
18
  - 🔢 **[simpleMath.md](./basics/simpleMath.md)** — A collection of simple math utilities for calculations like the Rule of Three and percentages.
19
19
  - ✍️ **[text.md](./basics/text.md)** — A utility for transforming text into title case formats, with multiple options for capitalization.
20
+ - 🔄 **[asyncReplace.md](./basics/asyncReplace.md)** — Asynchronously replaces matches in a string using a regex and an async function.
21
+
22
+ ### 2. **`libs/`**
23
+ - 🗂️ **[TinyPromiseQueue.md](./libs/TinyPromiseQueue.md)** — A class that allows sequential execution of asynchronous tasks, supporting task delays, cancellation, and queue management.
24
+ - 🏅 **[TinyLevelUp.md](./libs/TinyLevelUp.md)** — A class to manage user level-up logic based on experience points, providing methods for experience validation, addition, removal, and calculation.
20
25
 
21
26
  ---
22
27
 
@@ -0,0 +1,39 @@
1
+ ## `asyncReplace(str, regex, asyncFn)` 🔄
2
+
3
+ Asynchronously replaces matches in a string using a regular expression and an async function.
4
+
5
+ This function performs replacements on a string, allowing each match to be asynchronously replaced by calling an asynchronous function for each match. The asynchronous function should return a replacement value for each match and will receive the same arguments as the standard `replace` callback.
6
+
7
+ ### Parameters:
8
+
9
+ - `str` (`string`): The input string to perform replacements on.
10
+ - `regex` (`RegExp`): The regular expression used to match substrings for replacement.
11
+ - `asyncFn` (`Function`): An asynchronous function that returns a replacement for each match.
12
+ - It receives the same arguments as the standard `replace` callback (the matched substring and the matched string's groups).
13
+ - The function should return a `Promise` that resolves to the replacement value for that match.
14
+
15
+ ### Returns:
16
+ - `Promise<string>`: A promise that resolves to the resulting string with all async replacements applied.
17
+
18
+ ### Example:
19
+
20
+ ```javascript
21
+ await asyncReplace("Hello @user1 and @user2!", /@\w+/g, async (mention) => {
22
+ return await getUserNameFromMention(mention);
23
+ });
24
+ ```
25
+
26
+ In this example, each `@user` mention is asynchronously replaced by the value returned from `getUserNameFromMention`.
27
+
28
+ ### Description:
29
+
30
+ This function will:
31
+ 1. Use a regular expression (`regex`) to find all matches in the input string (`str`).
32
+ 2. For each match, it will invoke the provided asynchronous function (`asyncFn`), which should return the replacement value.
33
+ 3. Once all promises are resolved, it replaces the original matches in the string with the resolved values.
34
+
35
+ This is useful for scenarios where you need to replace parts of a string based on dynamic data (like fetching usernames from a server for each mention in a message).
36
+
37
+ ### Notes:
38
+ - The replacements are performed asynchronously, ensuring non-blocking behavior when dealing with large or external data sources.
39
+ - The function utilizes `Promise.all` to handle multiple asynchronous operations concurrently before replacing the matches in the original string.